Advertisement
  1. Code
  2. Jade

Creación de un menú desplegable para páginas móviles

Scroll to top
Read Time: 10 min

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:

PlaygroundPlaygroundPlayground

Fíjate en el código actual

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:

Hamburger Menu IconHamburger Menu IconHamburger Menu Icon

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.

Observa el actual código

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.

Observa el código actual

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 $ith 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
})

Observa el actual código

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.

Resultado final

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.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.