Spanish (Español) translation by Eva Collados Pascual (you can also view the original English article)
Este tutorial te enseñará cómo crear y animar un icono de menú de hamburguesa y, a continuación, adjuntar un detector de eventos a través de jQuery para desencadenar un menú desplegable.
Usaré Jade (Pug) y Sass en lugar de vanilla HTML y CSS. Así que al menos deberías tener un conocimiento básico de estos motores de plantillas.
Creación del área de juegos
Comenzaremos con la implementación de un simple patio de recreo. Solo voy a proporcionar la plantilla de Jade junto con el estilo Sass, ya que este no es el ámbito del tutorial. Puedes tomarlo y usarlo o puedes crear tu propio diseño.
Archivo Jade:
1 |
body
|
2 |
#container
|
3 |
#header
|
4 |
#body
|
5 |
.content |
6 |
.left |
7 |
.right |
8 |
- for (i=1; i <= 5 ; i++ ) |
9 |
div( id="text" + i ) |
10 |
.content |
11 |
.left |
12 |
.right |
13 |
- for (j=6; j <= 10 ; j++ ) |
14 |
div( id="text" + j ) |
15 |
.content |
16 |
.left |
17 |
.right |
18 |
- for (k=11; k <= 15 ; k++ ) |
19 |
div( id="text" + k ) |
Archivo Sass:
1 |
=flex() |
2 |
display: -webkit-box |
3 |
display: -moz-box |
4 |
display: -ms-flexbox |
5 |
display: -webkit-flex |
6 |
display: flex |
7 |
|
8 |
=transition($time) |
9 |
-webkit-transition: all $time ease |
10 |
-moz-transition: all $time ease |
11 |
-ms-transition: all $time ease |
12 |
-o-transition: all $time ease |
13 |
transition: all $time ease |
14 |
|
15 |
html, body |
16 |
margin: 0 |
17 |
padding: 20px 0 |
18 |
+flex() |
19 |
justify-content: center |
20 |
|
21 |
//----------------------------------// |
22 |
|
23 |
#container
|
24 |
width: 320px |
25 |
height: 550px |
26 |
background-color: #ebebeb |
27 |
overflow: hidden |
28 |
|
29 |
#header
|
30 |
height: 45px |
31 |
background-color: #9b9b9b |
32 |
position: relative |
33 |
|
34 |
|
35 |
#body
|
36 |
padding: 0 20px |
37 |
padding-top: 40px |
38 |
+flex() |
39 |
|
40 |
flex-direction: column |
41 |
justify-content: flex-start |
42 |
|
43 |
.content
|
44 |
+flex() |
45 |
|
46 |
flex-direction: row |
47 |
justify-content: flex-start |
48 |
margin-bottom: 25px |
49 |
|
50 |
|
51 |
.left
|
52 |
width: 100px |
53 |
height: 100px |
54 |
margin-right: 15px |
55 |
background-color: #e1e1e1 |
56 |
|
57 |
.right
|
58 |
@for $i from 1 through 15 |
59 |
#text#{$i} |
60 |
margin-top: 10px |
61 |
width: 50 + random(100) + px |
62 |
height: 10px |
63 |
background-color: #e1e1e1 |
Nota: Aquí he creado dos combinaciones llamados flex
y transition
. Las combinaciones facilitan la reutilización de algunas reglas CSS al agruparlas. Siempre que necesite añadir display:flex
con todos los prefijos de proveedor, puedo usar +flex()
en su lugar, gracias a la combinación.
Usaremos esta estructura y construiremos sobre ella en el resto del tutorial.
El resultado final debería tener este aspecto:



Icono del menú de hamburguesa
Ahora es el momento de crear un menú de hamburguesa sencillo pero atractivo y después lo animaremos a través de CSS.
Añade un nuevo div dentro de #header
y denomínalo #hamburger
. A continuación, crea dos divs secundarios dentro de #hamburger
. Deben tener una clase común y un ID distinto cada uno.
1 |
#hamburger
|
2 |
.strip#top |
3 |
.strip#bottom |
Ahora tenemos que aplicar estilo al div padre #hamburger
y a los divs secundarios con la clase común .strip
.
1 |
#hamburger
|
2 |
height: 100% |
3 |
width: 45 |
4 |
+flex() |
5 |
|
6 |
flex-direction: column |
7 |
justify-content: space-between |
8 |
padding-left: 20px |
Establecemos la altura del div de forma que iguale a la de su div padre, que es #header
, definiendo height: 100%
. Además, establecemos un valor de anchura para este div primario, que definirá su región "clicable".
A continuación, añadimos flexbox con todos los prefijos de proveedor mediante las combinaciones, la cuales hemos creado antes.
Dado que queremos que nuestros divs .strip
se posicionen verticalmente, establecemos flex-direction: column
y luego usamos justify-content: space-between
para poner espacio entre los divs .strip
.
Después tenemos que empujar esos divs uno junto al otro añadiendo un margen inferior y superior a los respectivos divs.
1 |
#top |
2 |
margin-top: 17px |
3 |
|
4 |
#bottom |
5 |
margin-bottom: 17px |
También añadimos padding-left: 20px
para mover los divs .strip
más hacia la derecha.
Lo siguiente es estilizar las tiras. Esto es relativamente fácil, basta definir el tamaño y el color de los divs.
1 |
.strip
|
2 |
width: 25px |
3 |
height: 2px |
4 |
background-color: #ffffff |
El resultado final con el icono del menú de hamburguesa debería tener este aspecto:



Lo siguiente es animar el icono del menú para que cuando se haga clic sobre él, se anime formando un signo cruzado.
Animando el icono del menú de hamburguesa
En este punto, vamos a usar jQuery básico para alternar algunas clases CSS.
Primero vamos a crear las clases CSS que vamos a alternar.
Vamos a utilizar la configuración de transformación y rotación de la propiedad transform
de CSS junto con la propiedad transition
.
En primer lugar, añade transiciones a los divs #top
y #bottom
mediante combinaciones con un parámetro de sincronización específico.
1 |
#top |
2 |
margin-top: 17px |
3 |
+transition(.25s) |
4 |
|
5 |
#bottom |
6 |
margin-bottom: 17px |
7 |
+transition(.25s) |
Ahora tenemos que definir el estilo de las clases que se van a alternar.
Vamos a rotar y transformar cada div .strip
individualmente, por lo que necesitamos alternar diferentes clases tanto para los divs #top
como para los divs #bottom
.
1 |
#top |
2 |
margin-top: 17px |
3 |
+transition(.25s) |
4 |
|
5 |
&.topRotate |
6 |
transform-origin: center |
7 |
transform: translateY(4px) rotateZ(45deg) |
8 |
|
9 |
#bottom |
10 |
margin-bottom: 17px |
11 |
+transition(.25s) |
12 |
|
13 |
&.bottomRotate |
14 |
transform-origin: center |
15 |
transform: translateY(-5px) rotateZ(-45deg) |
Aquí definimos el estilo para dos clases diferentes denominadas .bottomRotate
y .topRotate
, que se añadirán y eliminarán de sus respectivos divs de referencia, #top
y #bottom
.
Ten en cuenta que el tamaño diferente de la clase .strip
daría lugar a la necesidad de diferentes valores translateY
y rotateZ
para crear una animación adecuada del signo cruzado.
Alternar clases con jQuery
Definimos cómo se animará cada div .strip
cuando las clases topRotate
y bottomRotate
estén presentes. Sin embargo, todavía no hemos adjuntado un detector de eventos para alternar esas clases.
Crea un nuevo archivo JavaScript y utiliza el siguiente código para alternar las clases topRotate
y bottomRotate
a divs con los IDs #top
y #bottom
respectivamente.
1 |
$(document).ready(function(){ |
2 |
$("#hamburger").click(function(){ |
3 |
$("#top").toggleClass("topRotate"); |
4 |
$("#bottom").toggleClass("bottomRotate"); |
5 |
});
|
6 |
})
|
Ponemos todo nuestro código dentro de $(document).ready(function(){})
para esperar a que toda la página se cargue antes de realizar cualquier acción.
Al hacer clic en el el div #hamburger
, alternará las clases de los divs con IDs específicos.
Nota: No olvides añadir el archivo jQuery fuente al proyecto.
Creación de la lista del menú
El siguiente paso consiste en crear un menú con elementos de lista.
Utiliza la siguiente estructura bajo #header
:
1 |
#dropDown |
2 |
#background |
3 |
ul |
4 |
li Home |
5 |
li Blog |
6 |
li Projects |
7 |
li Authors |
8 |
li Jobs |
9 |
li Contact |
Así que aquí usamos la etiqueta ul
como el padre con el fin de agrupar los elementos con etiquetas li
como descendientes. Además, con el fin de crear una animación de expansión en el fondo, también hemos añadido un div con el ID #background
.
Vamos a aplicar estilo a los elementos ul
y li
primero.
1 |
ul
|
2 |
list-style: none |
3 |
padding: 0 |
4 |
margin: 0 |
Establece list-style
a none
para quitar las viñetas de los elementos dentro de ul
y fija también el padding
y el margin
a 0 para quitar todos los valores predefinidos.
Ahora aplica estilo los elementos li
:
1 |
li
|
2 |
//display: none |
3 |
background-color: #9b9b9b |
4 |
color: #ffffff |
5 |
|
6 |
font-family: 'Quicksand', sans-serif |
7 |
font-weight: lighter |
8 |
font-size: 15px |
9 |
padding: 20px |
10 |
padding-left: 60px |
11 |
|
12 |
&:after |
13 |
position: absolute |
14 |
content: '' |
15 |
left: 60px |
16 |
width: 60% |
17 |
height: 1px |
18 |
bottom: 4px |
19 |
background: rgba(255, 255, 255, 0.25) |
20 |
|
21 |
&:last-child:after |
22 |
width: 0 |
Aquí he comentado display:none
con el fin de poder comprobar el resultado. Sin embargo, durante la animación, lo usaremos para ocultar inicialmente los elementos de la lista.
También añadí el pseudo-elemento after
y le apliqué un estilo con el fin de separar cada elemento li
con una línea recta. :last-child:after
quita esta línea para el último elemento li
.
Animación de la lista de menús
Ahora vamos a utilizar algunas directivas de control de Sass para añadir keyframes (fotogramas clave) de animación CSS con diferentes atributos a cada elemento li
.
1 |
@keyframes drop |
2 |
0% |
3 |
opacity: 0 |
4 |
transform: scale(1.3) |
5 |
|
6 |
100% |
7 |
opacity: 1 |
8 |
transform: scale(1) |
9 |
|
10 |
@keyframes fold |
11 |
0% |
12 |
opacity: 1 |
13 |
transform: scale(1) |
14 |
|
15 |
100% |
16 |
opacity: 0 |
17 |
transform: scale(0.7) |
Aquí definimos nuestras animaciones de fotogramas clave drop
y fold
.
drop
sirve para animar la apertura de la lista del menú. El escalado inicial es un 30% más y se reduce al tamaño original a medida que la transparencia va de 0 a 1. La acción opuesta tiene lugar en fold
.
Ahora tenemos que adjuntar esos keyframes a los elementos li
. Esta es la parte en la que Sass nos resulta útil.
1 |
@for $i from 1 through 6 |
2 |
li:nth-child(#{$i}) |
3 |
animation: |
4 |
name: fold |
5 |
duration: 80ms*(6-$i) + 1ms |
6 |
timing-function: ease-in-out |
7 |
fill-mode: forwards |
8 |
|
9 |
li.anim:nth-child(#{$i}) |
10 |
animation: |
11 |
name: drop |
12 |
duration: 100ms*$i |
13 |
timing-function: ease-in-out |
14 |
fill-mode: forwards |
Aquí utilicé un bucle for que va de 1 a 6 con el índice de $i
.
Ahora necesitamos usar este índice para adjuntar cada animación a elementos li
con diferentes duraciones.
En primer lugar, considera la línea li.anim:nth-child(#{$i})
.
Aquí estamos cogiendo el $i
th hijo del elemento li
con la clase anim
.
Vamos a alternar esta clase anim
. De manera que cuando sea añadida a los elementos li
, la animación del keyframe con el nombre de drop
será ejecutada. Cuando sea eliminada, la animación fold
entrará en acción.
Lo siguiente en importancia es el atributo duration
.
duration: 100 ms*$i
para la animación drop
está extendiendo la duración de la animación para cada incremento del número de un hijo. Por lo tanto, cuando este código es compilado, el primer hijo li
tendrá duration: 100 ms
, y el último hijo tendrá duration: 600ms
.
Esto proporcionará una sensación como si cada elemento se animase consecutivamente uno tras otro.
Hacemos lo mismo para la animación de fold
. Esta vez, el último elemento debe ser animado más rápido, por lo tanto establecemos duration: 80ms*(6-$i) + 1ms
. Los 1ms añadidos a la duración se deben al hecho de que cuando se establece la duración en 0, es probable que se produzcan algunos problemas y que la animación no funcione correctamente.
Cuando estábamos aplicando estilo al elemento li
, mencioné que necesitábamos usar display:none
para evitar la reproducción no deseada de la animación. Si no lo estableces en none
, verás que la animación de fold
se reproduce una vez que la página se ha cargado.
Si establecemos la propiedad display
en none
, no veremos eso, y después necesitamos mostrar el elemento li
antes de alternar la clase anim
.
Queremos que nuestras animaciones se reproduzcan cuando hagamos clic en el icono de la hamburguesa. Así que vamos a usar un poco de jQuery para establecer la propiedad display
de cada elemento li
a block
y también alternar la clase anim
.
1 |
$(document).ready(function(){ |
2 |
$("#hamburger").click(function(){ |
3 |
$("#top").toggleClass("topRotate"); |
4 |
$("#bottom").toggleClass("bottomRotate"); |
5 |
|
6 |
$("li").show(); |
7 |
$("li").toggleClass("anim"); |
8 |
|
9 |
});
|
10 |
})
|
Te habrás fijado que podemos ver la animación de cada elemento li
de forma individual. Sin embargo, preferimos tener una sensación de menú en expansión.
Para solucionarlo, simplemente debemos ampliar la altura de un div. Ese div es #background
, que inicialmente añadimos al crear los elementos ul
y li
.
1 |
#background
|
2 |
width: 100% |
3 |
height: 0 |
4 |
background-color: #9b9b9b |
5 |
position: absolute |
6 |
+transition(.45s) |
7 |
|
8 |
&.expand |
9 |
height: 550px |
Vamos a alternar la clase expand
para establecer el atributo height
en 550px
dentro de .45s
. Ten en cuenta que utilicé la combinación de transition
para definirla con un parámetro temporal específico.
Conclusión
A lo largo de este tutorial, hemos practicado cómo usar bucles dentro de HTML y CSS a través de los motores de plantillas Jade y Sass. Además de eso, creamos animaciones de keyframes CSS y las adjuntamos con diferentes atributos de duración a elementos HTML específicos. Luego alternamos las clases con jQuery para controlar esas animaciones.