Cómo ocultar/mostrar una cabecera fija durante el desplazamiento de la página con JavaScript
Spanish (Español) translation by Carlos (you can also view the original English article)
¿Alguna vez has visto una de esas barras de cabecera fijas (o «pegajosas») que desaparecen cuando empiezas a desplazarte por la página, y vuelven a aparecer cada vez que comienzas a desplazarte hacia arriba? En este ejercicio aprenderemos a crear la nuestra utilizando un poco de JavaScript.
¿Por qué?
Los componentes fijos o «pegajosos» (como las cabeceras o headers) son sumamente populares en el mundo del diseño web; pues pueden mantener los elementos esenciales de la interfaz de usuario (UI) a la vista de forma permanente, y son fácilmente accesibles en caso de que los usuarios los necesiten. No obstante, en determinadas circunstancias (si las cabeceras alojan mucho contenido, o si el tamaño y la orientación de la pantalla limitan la cantidad de su espacio disponible) las cabeceras fijas pueden resultar molestas.
«Cuando se implementan mal, los elementos de una navegación fija pueden distraer del contenido real».
Aaron Andre Chichioco
Una cabecera fija que desaparece de la vista cuando no se necesita (es decir, cuando el usuario se desplaza para ver más contenido) es un excelente equilibrio.
Podemos lograr este tipo de efecto usando una biblioteca externa como Headroom.js, pero vamos a aprender la mecánica que hay detrás, creándolo nosotros mismos. Como bonificación, también haremos que el menú de la cabecera sea completamente funcional, listo para que puedas añadir tu propia personalización.
Lo que vamos a crear
Esto es lo que vamos a crear (desplázate para probar su comportamiento):
¡Comencemos!
1. Inicia con el marcado de la página
Para iniciar con nuestra cabecera pegajosa, abriremos el marcado con un header
que contenga una etiqueta nav
. Adentro, colocaremos el botón para alternar el menú y el menú en sí. Solo para enriquecer la página con contenido ficticio, también definiremos tres secciones a pantalla completa. Añadiremos algunas imágenes de fondo de un tutorial previo.
Aquí está el marcado de la página:
<header class="page-header"> <nav> <div class="trigger-menu-wrapper"> <button class="trigger-menu"> <svg width="20" height="20" viewBox="0 0 24 24"> <path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z"/> </svg> <span>MENU</span> </button> </div> <ul class="menu">...</ul> </nav> </header> <main class="page-main"> <section>...</section> <section>...</section> <section>...</section> </main>
2. Añade el CSS de la cabecera fija (sticky header)
Agreguemos algunas reglas de CSS para mejorar el aspecto y (hasta cierto punto) el comportamiento de nuestra cabecera.
En aras de la simplicidad, no voy a repasar los estilos de restablecimiento iniciales, pero puedes verlos haciendo clic en la pestaña CSS del proyecto de demostración.
Los estilos de la cabecera son bastante simples, pero dos cosas son importantes:
- En primer lugar, tanto la envoltura del menú de conmutación como el menú serán elementos de posición fija.
- En segundo lugar, el menú estará inicialmente oculto.
Los estilos relacionados con la cabecera (header) son los siguientes:
/*CUSTOM VARIABLES HERE*/ .trigger-menu-wrapper { position: fixed; top: 0; left: 0; right: 0; display: flex; justify-content: center; padding: 10px; z-index: 2; background: var(--lightpurple); transition: transform 0.4s; } .page-header .trigger-menu { display: flex; align-items: center; font-size: 1.5rem; color: var(--white); } .page-header .trigger-menu svg { fill: var(--white); margin-right: 5px; transition: transform 0.3s; } .page-header .menu { position: fixed; top: 0; left: 0; right: 0; bottom: 0; display: none; text-align: center; padding: 15vh 0 5vh; overflow: auto; z-index: 1; } .page-header .menu a { font-size: 3rem; } .page-header .sub-menu a { font-size: 1.5rem; }
Las secciones se comportarán como elementos de pantalla completa con una imagen de fondo y una superposición oscura encima. Estos nos brindará algo para desplazarnos para que podamos ver el comportamiento de ocultar/mostrar de nuestra cabecera:
.page-main section { position: relative; background-repeat: no-repeat; background-position: center; background-size: cover; height: 100vh; } .page-main section::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.25); }
3. Añade el JavaScript
Como siguiente paso, vamos a añadir un poco de comportamiento al menú.
Menú de conmutación
Cada vez que hagamos clic en el botón de conmutación, la visibilidad del menú cambiará. Si está oculto, aparecerá. Pero si es visible, desaparecerá.
Estamos manejando esto de una forma bastante rudimentaria, pero te brinda la posibilidad de adaptar las cosas a tu gusto. Aquí está el código JavaScript requerido:
const body = document.body; const triggerMenu = document.querySelector(".page-header .trigger-menu"); triggerMenu.addEventListener("click", () => { body.classList.toggle("menu-open"); });
Y los estilos relacionados:
.page-header .trigger-menu svg { transition: transform 0.3s; } .menu-open { overflow: hidden; } .menu-open .page-header .menu { display: block; } .menu-open .page-header svg { transform: rotate(45deg); }
Como habrás notado, no hay ninguna animación durante los cambios en el estado del menú. Eso ocurre porque usé la propiedad display
que no se puede animar. Si deseas añadir algún tipo de animación, reemplaza esta propiedad con algo que sea posible animar como: opacity
o visibility
.
Alternando la cabecera
Ahora vamos a dirigir nuestra atención a algo más interesante.
Cada vez que nos desplazamos hacia abajo, el botón para conmutar (y la cabecera en general) debería desaparecer con una animación de «deslizamiento hacia fuera». Si luego nos desplazamos hacia arriba, debería aparecer con una animación de «deslizamiento hacia dentro».
Para implementar esta funcionalidad, usaremos dos clases auxiliares: scroll-up
y scroll-down
. De manera más específica:
- A medida que nos desplazamos hacia abajo,
body
recibirá la clasescroll-down
. - Cuando nos desplazamos hacia arriba, se le dará la clase
scroll-up
. - Si nos desplazamos a la parte superior de la página, perderá su clase
scroll-up
.
Para detectar la dirección del desplazamiento, almacenaremos la última posición del desplazamiento en una variable (lastScroll
). Al principio, el valor de esta variable será 0. Luego, a medida que nos desplacemos, comprobaremos si la nueva posición es mayor o menor que la anterior. Según el resultado de esa condición, aplicaremos la clase correspondiente a body
.
Aquí está el código JavaScript para controlar eso:
const body = document.body; const nav = document.querySelector(".page-header nav"); const menu = document.querySelector(".page-header .menu"); const scrollUp = "scroll-up"; const scrollDown = "scroll-down"; let lastScroll = 0; window.addEventListener("scroll", () => { const currentScroll = window.pageYOffset; if (currentScroll == 0) { body.classList.remove(scrollUp); return; } if (currentScroll > lastScroll && !body.classList.contains(scrollDown)) { // down body.classList.remove(scrollUp); body.classList.add(scrollDown); } else if (currentScroll < lastScroll && body.classList.contains(scrollDown)) { // up body.classList.remove(scrollDown); body.classList.add(scrollUp); } lastScroll = currentScroll; });
Y los estilos asociados:
/*CUSTOM VARIABLES HERE*/ .trigger-menu-wrapper { transition: transform 0.4s; } .scroll-down .trigger-menu-wrapper { transform: translate3d(0, -100%, 0); } .scroll-up .trigger-menu-wrapper { transform: none; } .scroll-up:not(.menu-open) .trigger-menu-wrapper { background: var(--lightpurple); box-shadow: 0 0 10px rgba(0, 0, 0, 0.35); }
Conclusión
¡Eso es todo, amigos! Durante este ejercicio aprendimos cómo alternar la visibilidad de una cabecera fija dependiendo de la dirección de desplazamiento.
Espero que este tutorial te haya sido útil y que lo aproveches en tus próximos proyectos. Como siempre, ¡muchas gracias por leernos!
Más tutoriales para efectos «pegajosos»
¡Quédate! Hay mucho más que aprender sobre el comportamiento pegajoso en el diseño web:
- PatronesCómo crear una cabecera fija que se anime al desplazar la páginaGeorge Martsoukos
- WordPressCómo crear un menú fijo en WordPressRachel McCollin
- CSSPosicionamiento fijo únicamente con CSSThoriq Firdaus
- Diseño de UICómo crear un video flotante y «pegajoso» al desplazar la páginaLouie Rootfield