Criando um ícone de menu animado com CSS

Provavelmente você já deve ter visto que a maioria dos ícones de menu utilizados hoje em dia, são daquele tipo hambúrguer (três linhas horizontais paralelas, com espaço entre elas) para mobile. Apesar de muita crítica a este tipo de menu por não serem muito intuitivos, eles refletem a existência de uma lista de opções que podem levar a algum link ou configuração no site ou aplicativo em que foi implantado.

Deixando o assunto de experiência de usuário (UX Design) um pouco de lado e voltando ao nosso tópico, hoje vou explicar como criar o famoso ícone de menu animado utilizando apenas CSS e HTML, nada de JavaScript.

Veja abaixo um exemplo do que vamos criar:

Ícone de menu animado

Perceba que o ícone do menu (as três linhas horizontais) se transforma em um "X" (fechar), que, quando clicado novamente, fecha as opções do menu.

Vamos ver como fazer isso logo abaixo.

Ícone de menu animado com CSS

Para atingir o nosso objetivo, precisaríamos capturar o evento de clique no menu para exibir o conteúdo, porém, hoje vamos utilizar aquela tática de capturar cliques em css com um input checkbox.

O HTML

Por isso, nosso HTML vai ficar assim:

<div class="entire-menu">

  <input type="checkbox" id="change-hamburguer" />

  <a class="hamburguer" href="#">
    <span></span>
    <label for="change-hamburguer"></label>
  </a>

  <div class="menu">
    <a href="#">Item</a>
    <a href="#">Item</a>
  </div>

</div>

Apesar de estarmos sacrificando a semântica do nosso HTML completamente (vários elementos vazios e fora do local) essa tática funciona muito bem em navegadores mais novos (do IE9 pra cima).

O CSS

Primeiramente, vamos personalizar o HTML e BODY para que a aparência fique um pouco mais legal:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background: url(https://www.todoespacoonline.com/w/wp-content/uploads/2014/07/01.png) no-repeat;
  background-size: cover;
}

Agora vamos posicionar o nosso DIV que envolve todo o menu (.entire-menu):

.entire-menu {
  position: absolute;
  padding: 20px;
  width: 100%;
}

Nada demais até aqui, só o posicionamento em si foi afetado.

Agora vamos configurar o ícone de menu animado em si:

.hamburguer {
  width: 20px;
  height: 20px;
  display: block;
  position: relative;
  background: none;
  margin: 0 0 10px 0;
}
.hamburguer:after, .hamburguer:before, .hamburguer span, .hamburguer label {
  content: ' ';
  display: block;
  width: 100%;
  height: 4px;
  background: black;
  left: 0;
  position: absolute;
  -webkit-transition: all 300ms ease-in-out;
  transition: all 300ms ease-in-out;
}
.hamburguer:before {
  top: 0;
}
.hamburguer:after {
  bottom: 0;
}
.hamburguer:focus {
  outline: none;
}
.hamburguer label {
  width: 100%;
  height: 100%;
  background: none;
  cursor: pointer;
  z-index: 1000;
}
.hamburguer span {
  top: 8px;
}

Em seguida, "capturamos o clique em CSS" e configuramos a animação das linhas:

#change-hamburguer {
  display: none;
}
#change-hamburguer:checked ~ .hamburguer:before, #change-hamburguer:checked ~ .hamburguer:after {
  top: 10px;
  margin-top: -10%;
}
#change-hamburguer:checked ~ .hamburguer:before {
  -ms-transform: rotate(-45deg);
  -webkit-transform: rotate(-45deg);
  transform: rotate(-45deg);
}
#change-hamburguer:checked ~ .hamburguer:after {
  -ms-transform: rotate(45deg);
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
}
#change-hamburguer:checked ~ .hamburguer span {
  opacity: 0;
}
#change-hamburguer:checked ~ .menu {
  max-height: 200px;
}

Por fim, completamos nosso CSS configurando apenas o conteúdo do menu em si:

.menu {
  max-height: 0;
  height: auto;
  background: #000;
  -webkit-transition: all 300ms ease-in-out;
  transition: all 300ms ease-in-out;
  overflow: hidden;
  font-family: sans-serif;
  font-weight: 400;
  font-size: 13px;
  width: 50%;
}
.menu a {
  text-decoration: none;
  color: #fff;
  padding: 5px 10px;
  display: block;
  text-transform: uppercase;
  border-left: 5px solid #000;
}
.menu a:hover {
  border-left: 5px solid #e57373;
  color: #e57373;
  background: #222;
}

E como resultado temos o exemplo abaixo:

Codepen 1

Muito legal o efeito.

Menu animado em Sass (scss)

Se você gosta de desenvolver em sass, criei um código que faz tudo sozinho, você só vai precisar alterar a cor e o tamanho do botão se desejar, veja abaixo:

$button-size: 20px;
$button-color: #000;

@function calc-line-height($n) {
  @return $n / 5;
}

@mixin css3-rotation($n){
  -ms-transform:rotate($n);
  -webkit-transform:rotate($n);
  transform: rotate($n);
}

*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body{
  background: url(https://www.todoespacoonline.com/w/wp-content/uploads/2014/07/01.png) no-repeat;
  background-size: cover;
}
.entire-menu{
  position: absolute;
  padding: 20px;
  width: 100%;
}
.hamburguer{
  width: $button-size;
  height: $button-size;
  display: block;
  position: relative;
  background: none;
  margin: 0 0 10px 0;
  
  &:after, &:before, span, label{
    content: ' ';
    display: block;
    width: 100%;
    height: calc-line-height( $button-size );
    background: $button-color;
    left:0;
    position: absolute;
    -webkit-transition: all 300ms ease-in-out; 
    transition: all 300ms ease-in-out;
  }
  &:before{
    top: 0;
  }
  &:after{
    bottom: 0; 
  }
  &:focus{
    outline: none;
  }
  label{
    width: 100%;
    height: 100%;
    background: none;
    cursor: pointer;
    z-index: 1000;
  }
  span{
    top: calc-line-height( $button-size ) * 2;
  }
}

#change-hamburguer{
  display:none;
  
  &:checked ~ .hamburguer:before, &:checked ~ .hamburguer:after {
    top: $button-size / 2;
    margin-top: -10%;
  }
  &:checked ~ .hamburguer:before{
		@include css3-rotation(-45deg);
  }
  &:checked ~ .hamburguer:after{
		@include css3-rotation(45deg);
  }
  &:checked ~ .hamburguer span{
		opacity: 0;
  }
  &:checked ~ .menu{
    max-height: 200px;
  }
}
.menu{
  max-height: 0;
  height: auto;
  background: #000;
  -webkit-transition: all 300ms ease-in-out; 
  transition: all 300ms ease-in-out;
  overflow: hidden;
  font-family: sans-serif;
  font-weight: 400;
  font-size: 13px ;
  width: 50%;
  
  a {
  	text-decoration: none;
    color: #fff;
    padding: 5px 10px;
    display: block;
    text-transform: uppercase;
    border-left: 5px solid #000;
    
    &:hover{
      border-left: 5px solid #e57373;
      color: #e57373;
      background: #222;
    }
  }

}

Se desejar alterar o estilo, edite primeiramente o valor das variáveis nas primeiras linhas.

Compatibilidade dos navegadores

Como utilizamos táticas um pouco avançadas, os trechos de códigos exibidos anteriormente só vão funcionar em navegadores mais novos, como o Internet Explorer 9 e superiores.

Avalie bem antes de utilizar este tutorial em seus projetos.