Advertisement
  1. Web Design
  2. JavaScript

Habilidades en JavaScript: crea una animación para una cabecera responsiva durante el desplazamiento de la página

Scroll to top
Read Time: 10 min

Spanish (Español) translation by Ana Paulina Figueroa (you can also view the original English article)

En este tutorial, aprenderemos cómo animar elementos de la cabecera durante el desplazamiento de la página. En primer lugar, crearemos una cabecera de navegación superior totalmente responsiva con tres diseños diferentes: uno para pantallas pequeñas, otro para pantallas medianas y uno para pantallas grandes y de mayor tamaño.

A continuación, animaremos sutilmente su botón de llamada a la acción en pantallas medianas y de mayor tamaño después de una cierta cantidad de desplazamiento. ¿Suena lo suficientemente interesante como para acompañarme en el trayecto?

Lo que estaremos construyendo

Este es un video de demostración que muestra el comportamiento de nuestra cabecera de página:

Esta es la demostración de Codepen correspondiente (consulta la versión más grande para ver cómo cambia el diseño):

¡Comencemos!

1. Empieza con el marcado de la página

Nuestra página estará compuesta por una cabecera y dos secciones auxiliares. Dentro de la cabecera, colocaremos una barra de navegación. Esta incluirá lo siguiente:

  • Un logotipo de tipo imagen.
  • El menú principal. Sus últimos tres elementos serán visibles solo en pantallas pequeñas.
  • El menú secundario. Este aparecerá en pantallas de más de 767px. En pantallas más pequeñas, sus elementos formarán parte del menú principal.
  • Un botón responsable del cambio al menú móvil. Este será visible en pantallas de hasta 1100 píxeles.

Este es el marcado:

1
<header class="page-header">
2
  <nav>
3
    <a href="">
4
      <img src="IMG_SRC" alt="">
5
    </a>
6
    <ul class="main-menu">
7
      <li>
8
        <a href="">Work</a>
9
      </li>
10
      <li>
11
        <a href="">About</a>
12
      </li>
13
      <li>
14
        <a href="">Clients</a>
15
      </li>
16
      <li>
17
        <a href="">News</a>
18
      </li>
19
      <li>
20
        <a href="">Login</a>
21
      </li>
22
      <li>
23
        <a href="">Pricing</a>
24
      </li>
25
      <li class="btn-wrapper">
26
        <a href="" class="btn">Sign Up</a>
27
      </li>
28
    </ul>
29
    <ul class="secondary-menu">
30
      <li>
31
        <a href="">Login</a>
32
      </li>
33
      <li>
34
        <a href="">Pricing</a>
35
      </li>
36
      <li>
37
        <a href="" class="btn">Sign Up</a>
38
      </li>
39
    </ul>
40
    <button class="toggle-mobile-menu" aria-label="Open Mobile Menu" type="button">
41
      <svg width="40" height="40" viewBox="0 0 24 24" fill="none" class="open-menu" aria-hidden="true">...</svg>
42
      <svg width="40" height="40" viewBox="0 0 24 24" fill="none" class="close-menu" aria-hidden="true">...</svg>
43
    </button>
44
  </nav>
45
</header>
46
<section class="hero">...</section>
47
<section class="main-content">...</section>

Más allá de la cabecera, crearemos dos secciones con contenido ficticio para probar el efecto del desplazamiento. Para mantener las cosas simples, no discutiremos los estilos de estos elementos.

Nota #1: para evitar crear contenido duplicado, en lugar de agregar los últimos tres elementos del menú principal a través de HTML, podríamos haberlos agregado dinámicamente a través de JavaScript. Recuerda que, inicialmente, estos son parte del menú secundario.

Nota #2: para este tutorial, no cubriré el tema de cómo hacer que el menú móvil sea totalmente accesible. Solamente he usado el atributo aria-label, cuyo valor será actualizado a través de JavaScript y del atributo aria-hidden.

2. Define algunos estilos básicos

Con el marcado listo, definiremos algunos estilos CSS básicos. Estos incluirán una fuente de Google, algunas variables personalizadas y algunas reglas de restablecimiento:

1
:root {
2
  --white: white;
3
  --deeppurple: #7c2a8a;
4
}
5
6
* {
7
  padding: 0;
8
  margin: 0;
9
  box-sizing: border-box;
10
}
11
12
ul {
13
  list-style: none;
14
}
15
16
button {
17
  background: none;
18
  border: none;
19
  outline: none;
20
  cursor: pointer;
21
}
22
23
a {
24
  text-decoration: none;
25
  color: inherit;
26
}
27
28
::-webkit-scrollbar {
29
  width: 10px;
30
}
31
32
::-webkit-scrollbar-track {
33
  box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.35);
34
}
35
36
::-webkit-scrollbar-thumb {
37
  background: var(--deeppurple);
38
}
39
40
body {
41
  font: 20px/1.5 "Inter", sans-serif;
42
}

Dentro de los estilos anteriores, y solo por diversión, agregamos algunos estilos para personalizar el estilo predeterminado de la barra de desplazamiento.

Customizing the default scrollbar styling

Ten en cuenta que no todos los navegadores (por ejemplo Firefox 80) adoptarán esta nueva apariencia.

Además, especificaremos tres clases auxiliares para controlar la visibilidad de nuestros elementos. Las usaremos más tarde, cuando cambiemos al menú móvil a través de JavaScript. Sus nombres están inspirados en los nombres de las clases de Bootstrap 4:

1
.d-block {
2
  display: block !important;
3
}
4
5
.d-flex {
6
  display: flex !important;
7
}
8
9
.d-none {
10
  display: none !important;
11
}

Observa que todas incluyen la propiedad important. Como regla general deberíamos evitar el uso de esta propiedad, porque causa problemas con los estilos y dificulta la depuración. Sin embargo, en nuestro ejemplo la usaremos para aplicar estilos a través de JavaScript a elementos con diferentes niveles de especificidad.

3. Establece los estilos de la cabecera

Para crear el diseño de la cabecera, seguiremos un enfoque centrado en el escritorio.

Pantallas grandes

En pantallas grandes (>1100px), su diseño debería verse así:

The header layout on large screensThe header layout on large screensThe header layout on large screens

En este punto:

  • La cabecera será un elemento con un una posición fija y una altura estática.
  • La navegación será un contenedor flexible. Su contenido estará centrado verticalmente a lo largo del eje transversal y horizontalmente distribuido a lo largo del eje principal.
  • El menú principal también será un contenedor flexible con elementos centrados verticalmente.
  • De forma predeterminada, el último elemento (el botón de llamada a la acción) del menú secundario estará fuera de la pantalla. Para sacarlo de la pantalla, le asignaremos transform: translateX(200px) a su lista padre. El número 200 se obtiene sumando el ancho del botón (150px) y la cantidad de espaciado (50px) entre los elementos de la lista del menú secundario.
  • El botón de cambio de tipo hamburguesa estará oculto. Ese también contendrá dos iconos tomados de CSS.gg.

Los estilos relacionados:

1
/*CUSTOM VARIABLES HERE*/
2
3
.page-header {
4
  position: fixed;
5
  top: 0;
6
  left: 0;
7
  right: 0;
8
  bottom: 0;
9
  z-index: 1;
10
  height: 100px;
11
}
12
13
.page-header nav {
14
  position: relative;
15
  display: flex;
16
  justify-content: space-between;
17
  align-items: center;
18
  height: 100%;
19
  padding: 0 15px;
20
  background: var(--white);
21
  box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.15);
22
}
23
24
.page-header ul {
25
  display: flex;
26
  align-items: center;
27
}
28
29
.page-header .main-menu {
30
  margin-left: 100px;
31
}
32
33
.page-header .main-menu li:nth-last-child(-n + 3) {
34
  display: none;
35
}
36
37
.page-header .secondary-menu {
38
  transform: translateX(200px);
39
  transition: transform 0.3s ease-out;
40
}
41
42
.page-header li:not(:last-child) {
43
  margin-right: 50px;
44
}
45
46
.page-header .btn {
47
  display: inline-block;
48
  width: 150px;
49
  text-align: center;
50
  font-weight: 900;
51
  padding: 12px 6px;
52
  border-radius: 5px;
53
  color: var(--white);
54
  background: var(--deeppurple);
55
}
56
57
.page-header a {
58
  font-size: 18px;
59
  color: var(--deeppurple);
60
}
61
62
.page-header .toggle-mobile-menu {
63
  display: none;
64
  position: absolute;
65
  top: 50%;
66
  left: 50%;
67
  transform: translate(-50%, -50%);
68
}
69
70
.page-header .toggle-mobile-menu .close-menu {
71
  display: none;
72
}
73
74
.page-header .toggle-mobile-menu path {
75
  fill: var(--deeppurple);
76
}

Pantallas medianas

En pantallas medianas (≥768px y ≤1100px), su diseño debería verse así:

The header layout on medium screensThe header layout on medium screensThe header layout on medium screens

En este punto:

  • El menú principal tendrá una posición absoluta y se desplazará por debajo de la cabecera. También estará oculto de forma predeterminada y aparecerá cuando hagamos clic en el botón de hamburguesa. Además, sus elementos estarán distribuidos equitativamente a lo largo de su padre.
  • El botón de llamada a la acción aún se encuentra fuera de la pantalla, pero esta vez le asignaremos transform: translateX(170px) a su padre, ya que el espacio entre los elementos de la lista se reduce a 20 píxeles.
  • El botón de cambio de tipo hamburguesa se hará visible.

Los estilos asociados:

1
/*CUSTOM VARIABLES HERE*/
2
3
@media screen and (max-width: 1100px) {
4
  .page-header img {
5
    max-width: 140px;
6
  }
7
8
  .page-header .main-menu {
9
    display: none;
10
    position: absolute;
11
    top: 100px;
12
    left: 0;
13
    right: 0;
14
    padding: 15px;
15
    margin-left: 0;
16
    text-align: center;
17
    z-index: 1;
18
    background: var(--white);
19
    box-shadow: 0 6px 10px rgba(0, 0, 0, 0.15);
20
  }
21
22
  .page-header .main-menu li {
23
    flex: 1;
24
  }
25
26
  .page-header .secondary-menu {
27
    transform: translateX(170px);
28
  }
29
  .page-header li:not(:last-child) {
30
    margin-right: 20px;
31
  }
32
33
  .page-header .toggle-mobile-menu {
34
    display: block;
35
  }
36
}

Pantallas pequeñas

Finalmente, en pantallas estrechas (<768px), su diseño debería verse de esta manera:

The header layout on small screensThe header layout on small screensThe header layout on small screens

En este punto:

  • Los elementos del menú principal se apilarán. Además, los últimos tres elementos se harán visibles.
  • El menú secundario estará oculto.
  • No habrá ninguna animación durante el desplazamiento de la página. La llamada a la acción será visible de forma predeterminada, con una posición absoluta y como parte del menú móvil.

Los estilos correspondientes:

1
@media screen and (max-width: 767px) {
2
  .page-header {
3
    height: 70px;
4
  }
5
6
  .page-header .main-menu {
7
    top: 70px;
8
    flex-direction: column;
9
    align-items: start;
10
  }
11
12
  .page-header .main-menu li {
13
    flex-grow: 0;
14
  }
15
16
  .page-header .main-menu li + li {
17
    margin-top: 15px;
18
  }
19
  
20
  .page-header .main-menu li:nth-last-child(-n + 3) {
21
    display: block;
22
  }
23
24
  .page-header .secondary-menu {
25
    display: none;
26
  }
27
28
  .page-header .toggle-mobile-menu {
29
    position: static;
30
    transform: none;
31
  }
32
33
  .page-header .btn-wrapper {
34
    position: absolute;
35
    top: 0;
36
    right: 15px;
37
  }
38
39
  .page-header .btn {
40
    width: 120px;
41
    padding: 8px 16px;
42
  }
43
}


4. Crea una animación durante el desplazamiento de la pantalla

A medida que nos desplacemos dentro de la pantalla, haremos un seguimiento de qué tanto nos hemos desplazado y, al habernos desplazado una cantidad de espacio determinada, animaremos sutilmente la visibilidad del botón de la cabecera cambiando la clase show-btn.

The animated call-to-action buttonThe animated call-to-action buttonThe animated call-to-action button

En nuestro ejemplo, el botón aparecerá tan pronto como la sección hero desaparezca, y viceversa.

En tus proyectos, puedes cambiar fácilmente cuándo debería aparecer el botón dependiendo de la cantidad de desplazamiento a través de la variable targetScroll. Aquí puedes enviar ya sea un valor fijo o uno dinámico.

Este es el código de JavaScript necesario:

1
const pageHeader = document.querySelector(".page-header");
2
const animatedUl = pageHeader.querySelector(".secondary-menu");
3
const showBtn = "show-btn";
4
let targetScroll = window.innerHeight - pageHeader.offsetHeight;
5
6
window.addEventListener("scroll", () => {
7
  const scrollY = this.pageYOffset;
8
9
  if (scrollY > targetScroll) {
10
    animatedUl.classList.add(showBtn);
11
  } else {
12
    animatedUl.classList.remove(showBtn);
13
  }
14
});
15
16
window.addEventListener("resize", () => {
17
  targetScroll = window.innerHeight - pageHeader.offsetHeight;
18
});

Y la clase CSS destino:

1
.page-header .secondary-menu.show-btn {
2
  transform: none;
3
}


5. Cambia el menú móvil

Como último paso, para que la cabecera sea totalmente responsiva, vamos a crear la funcionalidad del menú móvil.

Tan pronto como hagamos clic en el botón de hamburguesa, la visibilidad del menú móvil será cambiada. En ese momento haremos uso de las clases auxiliares en gran medida.

Este es el código de JavaScript pertinente:

1
const pageHeader = document.querySelector(".page-header");
2
const mainMenu = pageHeader.querySelector(".main-menu");
3
const openMenu = pageHeader.querySelector(".open-menu");
4
const closeMenu = pageHeader.querySelector(".close-menu");
5
const toggleMobileMenu = pageHeader.querySelector(".toggle-mobile-menu");
6
const dNone = "d-none";
7
const dBlock = "d-block";
8
const dFlex = "d-flex";
9
10
toggleMobileMenu.addEventListener("click", function () {
11
  mainMenu.classList.toggle(dFlex);
12
  if (!openMenu.classList.contains(dNone)) {
13
    this.setAttribute("aria-label", "Close Mobile Menu");  
14
    openMenu.classList.remove(dBlock);
15
    openMenu.classList.add(dNone);
16
    closeMenu.classList.remove(dNone);
17
    closeMenu.classList.add(dBlock);
18
  } else {
19
    this.setAttribute("aria-label", "Open Mobile Menu");
20
    openMenu.classList.remove(dNone);
21
    openMenu.classList.add(dBlock);
22
    closeMenu.classList.remove(dBlock);
23
    closeMenu.classList.add(dNone);
24
  }
25
});


¡Has creado una animación para una cabecera responsiva durante el desplazamiento de la página!

¡Eso es todo, amigos! Hoy discutimos cómo crear cabeceras de página responsivas con contenido animado durante el desplazamiento. Como vimos, con solo unos cuantos pasos podemos crear este tipo de funcionalidad y hacer páginas llamativas.

Echemos un vistazo a nuestra creación nuevamente:

¿Alguna vez has creado una cabecera animada de este tipo para un proyecto en el pasado? Si es así, ¿qué increíbles técnicas has usado?

Como siempre, ¡muchas gracias por leer!

Más tutoriales con cabeceras animadas durante el desplazamiento de la página

Aprende más sobre cómo animar cabeceras de páginas durante su desplazamiento con estos tutoriales:

Y si necesitas un repaso de Flexbox, echa un vistazo a estos tutoriales:

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 Web Design 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.