Barras de navegação em dispositivos móveis devem ser pensadas de antemão e criadas para serem confortáveis e fáceis de usar, e você consegue fazer elas sem usar JavaScript.
Normalmente, a navegação é escondida em um menu especial chamado de "hambúrguer", que se revela após um botão ser pressionado. Isso faz com que o conteúdo do site se torne mais relevante e o cabeçalho ocupe menos espaço.
Apesar do JavaScript ser o caminho mais utilizado para criar esse tipo de menu, além de ser uma adição bem leve que não afeta a performance do seu site, é possível implementar essa mesma funcionalidade usando apenas HTML e CSS.
Os navegadores já apresentam elementos e subclasses nativas para criar essa interatividade sem a necessidade de código extra, apenas utilizando inputs, labels, e as pseudo classes :has() e :checked. Todas amplamente suportadas desde versões antigas.
Ir por esse caminho também ajudará você a compreender mais como o CSS seleciona elementos com base em suas posições no DOM e ser mais criativo na hora de criar elementos interativos sem a necessidade de inserir JavaScript em sua página.
Criando o Toggler
O Toggler é o botão responsável por alterar entre os estados de aberto e fechado do menu.
Pensando em botão, lembramos do elemento <button> do HTML. Porém, ele por si só não consegue armazenar um estado a menos que adicionado manualmente via código.
Um outro elemento do HTML que possui esse comportamento nativo é o <input> do tipo checkbox. Com ele podemos checar seu estado através da pseudo classe :checked:
<!-- HTML -->
<input type="checkbox" />
/* CSS */
input:checked { }
Somente com esse input, já inserimos um botão do tipo toggler em nosso site. Porém, ele por si só não é muito descritivo, nem muito bonito, portanto podemos melhorá-lo da seguinte forma:
- Envolve-lo com um
<label>; - Adicionar um ícone de menu hambúrguer;
- Esconder o input;
- Adicionar um CSS extra para estilizar o botão:
<!-- Botão Toggler -->
<label class="toggler">
<!-- Input -->
<input type="checkbox" />
<!-- Ícone -->
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path d="M0 0h24v24H0z" fill="none" />
<path fill="currentColor" d="M3 18v-2h18v2zm0-5v-2h18v2zm0-5V6h18v2z" />
</svg>
</label>
.toggler {
display: inline-flex;
padding: 8px;
border: solid 1px rgba(0 0 0 / 30%);
border-radius: 4px;
}
.toggler input {
display: none;
}
Nesse momento, o estilo do botão é estático, e apesar de ele funcionar, não temos um feedback visual apropriado. Podemos fazer com que o estilo do botão mude com base no estado do input utilizando a pseudo classe :has(:checked):
.toggler:has(:checked) {
background-color: black;
color: white;
}
E agora quando a checkbox for marcada (ou em outras palavras, o menu for aberto), o botão ficará com as cores invertidas:
Por que :has(:checked) e não .toggler input:checked?
Para que esse efeito funcione, é preciso que a <label> seja a estilizada, e não o <input>.
Pelas regras de seleção do CSS, quando abrimos um seletor de criança, o parente não é o escolhido, e sim a criança. Nesse caso, se utilizássemos a segunda opção, o selecionado seria o <input> e não o <label>, causando um comportamento não esperado.
:has() é uma pseudo classe que faz a verificação interna do parente, mas não muda a seleção, e com ele podemos fazer essas seleções mais complexas. Nesse caso, se qualquer criança da <label> der como verdadeiro a condição :checked, então a regra é aplicada à <label>.
Criando o menu de navegação
A barra de navegação é a parte mais comum até o momento. Uma estrutura simples e bem reconhecida:
<nav class="navbar">
<ul>
<li><a href="/pagina1">Página 1</a></li>
<li><a href="/pagina2">Página 2</a></li>
<li><a href="/pagina3">Página 3</a></li>
</ul>
</nav>
Mas é muito importante que o menu venha depois do toggler. Nós usaremos o seletor de vizinho do CSS e a mesma tática da pseudo classe :has() para controlar o estado de visibilidade da navbar:
<label class="toggler"><!-- ... --></label>
<nav class="navbar"><!-- ... --></nav>
.navbar {
display: none;
}
.toggler:has(:checked) + .navbar {
display: block;
}
Com isso, já temos uma barra de navegação colapsável funcional, mas para tornar isso realmente confortável no mobile, precisamos fazer algumas alterações no estilo e na estrutura:
- Envolver todo esse código em um
<header>; - Estilizar a barra de navegação para um formato mais fácil de clicar;
- E para finalizar, adicionar um indicador de página atual:
<header class="header">
<label class="toggler"><!-- ... --></label>
<nav class="navbar">
<ul>
<li><a href="/pagina1" class="active">Página 1</a></li>
<li><a href="/pagina2">Página 2</a></li>
<li><a href="/pagina3">Página 3</a></li>
</ul>
</nav>
</header>
.header {
position: relative;
background-color: rgba(0 0 0 / 10%);
padding: 8px;
}
.navbar {
display: none;
position: absolute;
width: 100%;
left: 0;
top: 100%;
background-color: rgba(0 0 0 / 10%);
}
.navbar ul {
list-style-type: none;
padding: 0;
margin: 0;
}
.navbar a {
display: block;
padding: 8px 16px;
color: black;
text-decoration: none;
}
.navbar .active {
background-color: rgba(0 0 0 / 20%);
}
Bônus: Tailwind
Caso você esteja usando o Tailwind, fazer esse tipo de menu se torna uma tarefa muito mais fácil:
<header>
<label class="peer">
<input type="checkbox" class="hidden" />
<!-- icon here -->
</label>
<nav class="hidden peer-has-checked:block">
<!-- ... -->
</nav>
</header>




Top comments (0)