O título é bem auto descritivo, então vamos direto ao ponto. Para começar, esse é o nosso HTML, nada muito diferente do que você vê no dia a dia.
HTML
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Menu de navegação</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<header>
<h1>Meu site</h1>
<button class="btn-hamburger" type="button" title="Fechar">
<i></i>
<i></i>
<i></i>
</button>
<nav>
<ul>
<li class="close-button">
<button class="btn-hamburger" type="button" title="Fechar">
<i></i>
<i></i>
<i></i>
</button>
</li>
<li><a href="#">Home</a></li>
<li><a href="#">Sobre</a></li>
<li><a href="#">Contato</a></li>
</ul>
</nav>
</header>
</body>
</html>
No head temos apenas algumas tags definindo o titulo da página e linkando os nossos futuros arquivos style.css
e script.js
.
Já no body nós temos um header que contem o título do site, o nosso botão de menu, e uma tag nav
que vai ser nossa navbar. As tags <i></i>
dentro do botão de menu serão as responsáveis por formar os ícones de menu hambúrguer e de X no nosso botão, mas não vamos nos adiantar, já já falamos disso.
Dentro da nossa tag nav nós temos uma lista com os links de navegação para as outras páginas, e você deve ter reparado que o primeiro item da lista tem a mesma estrutura do botão de menu do header.
Não é erro de digitação, estamos repetindo ele dentro da navbar para que possamos fechar o menu quando ele estiver aberto, já que a ideia é que o menu sobreponha toda a página em telas pequenas, o que impede a gente de clicar naquele nosso botão do header para acionar o fechamento.
CSS
Passando para o CSS, vamos em partes, primeiro vamos definir algumas variáveis para deixar a nossa vida mais simples no futuro e dar um reset simples na página para não haver discrepância entre os navegadores:
/* style.css */
:root {
--bg: #222823; /* Cor de fundo do menu */
--fg: #575a5e; /* Cor de destaque */
--hamburger-btn-padding: 8px; /* Padding do botão de menu */
--hamburger-btn-size: 32px; /* Tamanho do botão de menu */
--hamburger-btn-gap: 4px; /* Espaçamento das linhas do botão de menu */
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: sans-serif;
}
Em seguida vamos customizar os botões da nossa página, apenas para deixar eles mais agradáveis:
/* style.css */
button {
border-radius: 4px;
border: none;
background-color: var(--bg);
transition: filter 300ms ease-out;
cursor: pointer;
}
button:hover {
filter: brightness(1.2);
}
Agora vamos estilizar nosso header, para que possamos diferenciá-lo do resto da página:
/* style.css */
header {
display: flex;
justify-content: space-between;
padding: 16px;
background-color: var(--bg);
color: #fff;
align-items: center;
}
Aqui eu estou aplicando o display: flex;
com justify-content: space-between;
para fazer com que o título fique do lado esquerdo e o botão de menu/navbar vá para o lado direito da tela.
No mais eu estou apenas aplicando um padding
para dar um espaço entre as bordas e um align-items: center
para deixar a o título e o botão/navbar alinhados.
Como eu estou usando uma cor de fundo escura, estou deixando a cor do texto branca para conseguir ler, caso você tenha usado uma cor clara para o fundo e esteja ruim de ler, basta alterar essa linha para melhorar a visibilidade do texto.
Agora vamos passar para o botão do menu.
/* style.css */
.btn-hamburger {
width: var(--hamburger-btn-size);
height: var(--hamburger-btn-size);
position: relative;
display: flex;
align-items: center;
justify-content: center;
gap: var(--hamburger-btn-gap);
flex-direction: column;
}
A classe btn-hamgurger
vai ser a responsável por identificar e estilizar os nossos botões de menu na página.
As customizações aqui consistem basicamente na definição da largura e da altura do botão. Além da definição da posição como relative
que nos vai ser útil na hora de animar o ícone do botão.
As demais mudanças servem apenas para manter as três tags <i></i>
centralizadas no botão e espaçadas igualmente umas das outras.
Agora é importante mencionar que o que irá definir se o menu está aberto ou não é a presença da classe active
. No botão essa classe será a responsável por estilizar as três tags i
como um X ao invés de um hambúrguer. Já na nav ela será a responsável por mostrar o menu em aparelhos com telas pequenas.
Estilizamos as tags i assim para que elas fiquem parecendo com as barras de um botão de menu:
/* style.css */
.btn-hamburger i {
height: 2px;
width: calc(var(--hamburger-btn-size) - 2 * var(--hamburger-btn-padding));
background-color: var(--fg);
border-radius: 4px;
transition: transform 150ms ease-in-out;
}
.btn-hamburger.active i {
position: absolute;
}
.btn-hamburger.active i {
transform: rotate(45deg);
}
.btn-hamburger.active i:nth-of-type(2) {
transform: rotate(-45deg);
}
O primeiro bloco de código apenas define a altura de cada barra e realiza um cálculo simples para definir a largura da barra como sendo a largura total do botão menos o padding
aplicado. O transition
está ali apenas para que a mudança de ícone ocorra de forma gradual como uma animação, ao invés de instantânea.
O segundo bloco de código muda o position
dessas tags para absolute
a fim de que elas consigam sobrepor umas as outras para formar o ícone de X.
Para transformar as três barras em um X, precisamos apenas rotacionar duas delas em 45 graus, e a outra em -45 graus, que é o que estamos fazendo no terceiro e quarto blocos de código.
Já para a navbar aplicaremos essas propriedades:
/* style.css */
nav {
width: 100vw;
min-height: 100dvh;
background-color: var(--bg);
position: absolute;
top: 0;
left: 100vw;
padding: 16px;
transition: left 150ms ease-out;
}
nav.active {
left: 0;
}
nav ul {
display: flex;
flex-direction: column;
list-style: none;
gap: 4px;
}
nav li.close-button {
align-self: flex-end;
}
nav a {
display: block;
width: 100%;
color: #fff;
text-decoration: none;
padding: 8px 12px;
border-radius: 8px;
transition: background 300ms ease-in-out;
}
nav a:hover {
background: var(--fg);
}
Aqui vamos focar no primeiro e segundo blocos de código, já que os demais são apenas estilização.
nav {
width: 100vw;
min-height: 100dvh;
background-color: var(--bg);
position: absolute;
top: 0;
left: 100vw;
padding: 16px;
transition: left 150ms ease-out;
}
nav.active {
left: 0;
}
Nesse primeiro bloco estamos fazendo a navbar ocupar um espaço correspondente a tela toda e então estamos usando as propriedades de posicionamento (position
, left
e top
) para fazer com que ela se desloque totalmente para a direita e saia da tela, a deixando fora de vista, já que a ausência da classe active
indica que ela deve estar fechada.
Por outro lado, quando a classe está presente devemos conseguir ver a navbar, pois ela estaria aberta. Nesse caso a gente define left: 0;
para fazer com que ela inicie do canto esquerdo da tela ao invés do direito e fique visível na tela.
Se você testar agora, vai que a animação até está funcionando, mas há dois problemas:
A navbar continua visível, estando apenas fastada para o lado criando uma rolagem horizontal tenebrosa na página toda
Não há responsividade: em telas grandes ela continua aparecendo como um menu lateral ao invés de uma navbar.
Então vamos resolver essas questões.
A primeira é bem simples, basta que mandemos o css esconder tudo que está para fora do body horiozntalmente:
/* style.css */
body {
font-family: sans-serif;
overflow-x: hidden; /* Adicione essa linha */
}
Para o segundo problema uma media query é suficiente para resolver:
/* style.css */
@media screen and (min-width: 768px) {
.btn-hamburger {
display: none;
}
nav {
position: initial;
min-height: auto;
width: auto;
background: none;
padding: 0;
}
nav ul {
flex-direction: row;
}
}
Nesses blocos de código estamos fazendo o seguinte:
Escondendo os botões de menu em telas grandes
Removendo a estilização que faz com que a navbar ocupe toda a tela e seja deslocada para fora da visão
Alterando a distribuições dos links de vertical para horizontal
Javascript
Por fim, agora temos que fazer os botões de menu provocarem as alterações de classe para que possamos abrir e fechar o menu:
// script.js
const hamburgerButtons = document.querySelectorAll('.btn-hamburger');
const navbar = document.querySelector('nav');
function menuToggle() {
hamburgerButtons.forEach((button) => button.classList.toggle('active'));
navbar.classList.toggle('active');
}
hamburgerButtons.forEach((button) => {
button.addEventListener('click', menuToggle);
});
Resultado
Se você seguiu tudo até aqui sem se perder, você deve ter algo mais ou menos assim nas suas telas grandes:
E algo assim nas suas telas pequenas:
E é isso, espero que tenha gostado! 😉
Top comments (0)