Cómo compilar un componente de navegación lateral

Descripción general de los conceptos básicos sobre cómo crear una barra lateral adaptable y deslizable

En esta publicación, quiero compartir contigo cómo creo un prototipo de un componente de navegación lateral para la Web que Tiene estado, admite la navegación con teclado, funciona con JavaScript y sin él. y funciona en todos los navegadores. Prueba la demostración.

Si prefieres ver un video, aquí tienes una versión de YouTube de esta publicación:

Descripción general

Es difícil crear un sistema de navegación responsivo. Algunos usuarios estarán en un teclado, Algunos tendrán computadoras de escritorio potentes y otros visitarán desde un dispositivo móvil pequeño. Todos los visitantes deberían poder abrir y cerrar el menú.

.
. Demostración del diseño responsivo de escritorio a dispositivo móvil
.
.
. El tema claro y oscuro está desactivado en iOS y Android
.

Tácticas web

En esta exploración de componentes, tuve la alegría de combinar algunas funciones fundamentales de la plataforma web:

  1. CSS :target
  2. Cuadrícula de CSS
  3. Transformaciones de CSS
  4. Consultas de medios de CSS para el viewport y las preferencias del usuario
  5. JS para focus mejoras de UX

Mi solución tiene una barra lateral y se activa solo cuando está en un dispositivo móvil viewport de 540px o menos 540px será nuestro punto de interrupción para cambiar entre el diseño interactivo para dispositivos móviles y el diseño estático para computadoras de escritorio.

Pseudoclase :target de CSS

Un vínculo <a> establece el hash de la URL en #sidenav-open y el otro en vacío (''). Por último, un elemento tiene el id para coincidir con el hash:

<a href="#sidenav-open" id="sidenav-button" title="Open Menu" aria-label="Open Menu">

<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>

<aside id="sidenav-open">
  …
</aside>

Cuando haces clic en cada uno de estos vínculos, cambia el estado de hash de la URL de nuestra página. Luego, con una seudoclase, muestro y oculto la navegación lateral:

@media (max-width: 540px) {
  #sidenav-open {
    visibility: hidden;
  }

  #sidenav-open:target {
    visibility: visible;
  }
}

Cuadrícula de CSS

Anteriormente, solo utilizaba la posición absoluta o fija diseños y componentes de navegación lateral. Sin embargo, la cuadrícula, con su sintaxis grid-area, nos permite asignar varios elementos a la misma fila o columna.

Pilas

El elemento de diseño principal #sidenav-container es una cuadrícula que crea 1 fila y 2 columnas, 1 de cada una se llama stack. Cuando el espacio es limitado, CSS asigna todos los elementos <main> secundarios al mismo nombre de cuadrícula, colocando todos los elementos en el mismo espacio y creando una pila.

#sidenav-container {
  display: grid;
  grid: [stack] 1fr / min-content [stack] 1fr;
  min-height: 100vh;
}

@media (max-width: 540px) {
  #sidenav-container > * {
    grid-area: stack;
  }
}

<aside> es el elemento de animación que contiene la navegación lateral. Tiene 2 elementos secundarios: el contenedor de navegación <nav> llamado [nav] y un fondo <a> llamado [escape], que se usa para cerrar el menú.

#sidenav-open {
  display: grid;
  grid-template-columns: [nav] 2fr [escape] 1fr;
}

Ajusta 2fr y 1fr para encontrar la proporción que te gusta para la superposición del menú y su botón de cierre con espacio negativo.

.
. Una demostración de lo que sucede cuando cambias la proporción.

Transformaciones CSS 3D y transiciones

Nuestro diseño ahora se apilan en un tamaño de viewport de dispositivo móvil. Hasta que no agregue algunos estilos nuevos, se superpone a nuestro artículo de forma predeterminada. Estas son algunas de las UX que necesito en esta próxima sección:

  • Cómo animar la apertura y el cierre
  • Solo animar con movimiento si el usuario está de acuerdo con eso.
  • Anima visibility para que el enfoque del teclado no ingrese al elemento fuera de pantalla

Cuando empiezo a implementar animaciones de movimiento, quiero tener en cuenta la accesibilidad como prioridad.

Movimiento accesible

No todo el mundo querrá una experiencia de movimiento de deslizamiento. En nuestra solución, esta preferencia se aplica ajustando una variable de CSS --duration dentro de una consulta de medios. Este valor de consulta de medios representa la preferencia del sistema operativo del usuario por el movimiento (si está disponible).

#sidenav-open {
  --duration: .6s;
}

@media (prefers-reduced-motion: reduce) {
  #sidenav-open {
    --duration: 1ms;
  }
}
Una demostración de la interacción con la duración aplicada y sin ella.

Cuando nuestro navegador lateral se deslice para abrir y cerrar, si un usuario prefiere un movimiento reducido Mueve el elemento instantáneamente a la vista y mantengo el estado sin movimiento.

Transición, transformación y traducción

Navegación lateral fuera (predeterminado)

Para establecer como predeterminado el estado "fuera de pantalla" de la navegación lateral en dispositivos móviles, Posicionar el elemento con transform: translateX(-110vw).

Ten en cuenta que agregué otro 10vw al código típico fuera de pantalla de -100vw, para asegurarte de que el elemento box-shadow del panel de navegación lateral no se muestre en el viewport principal cuando esté oculto.

@media (max-width: 540px) {
  #sidenav-open {
    visibility: hidden;
    transform: translateX(-110vw);
    will-change: transform;
    transition:
      transform var(--duration) var(--easeOutExpo),
      visibility 0s linear var(--duration);
  }
}
Navegación lateral en

Cuando el elemento #sidenav coincida como :target, establece la posición translateX() en la base 0, y observa cómo CSS desliza el elemento desde su posición de salida (-110vw) a su posición "adentro". de 0 sobre var(--duration) cuando se cambia el hash de la URL.

@media (max-width: 540px) {
  #sidenav-open:target {
    visibility: visible;
    transform: translateX(0);
    transition:
      transform var(--duration) var(--easeOutExpo);
  }
}

Visibilidad de la transición

El objetivo ahora es ocultar el menú a los lectores de pantalla cuando esté fuera para que los sistemas no se enfoquen en un menú fuera de pantalla. Logré esto estableciendo de visibilidad cuando cambia :target.

  • Cuando entres, no hagas la transición de la visibilidad. sea visible de inmediato para que pueda ver el elemento deslizarse y aceptar el enfoque.
  • Cuando salgas, realiza la transición de la visibilidad, pero retrasala, de modo que cambie a hidden al final de la transición.

Mejoras en la UX de accesibilidad

Esta solución se basa en el cambio de la URL para que se administre el estado. Como es de esperarse, se debe usar el elemento <a> aquí. Ofrece una buena accesibilidad. funciones de forma gratuita. Adornemos nuestros elementos interactivos con etiquetas que articulen claramente la intención.

<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>

<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
  <svg>...</svg>
</a>
Una demostración de la UX de interacción con el teclado y la voz en off.

Ahora, nuestros botones de interacción principales indican claramente su intención para el mouse y el teclado.

:is(:hover, :focus)

Este práctico pseudoselector funcional de CSS nos permite ser inclusivos rápidamente con nuestros estilos de desplazamiento del cursor compartiéndolos también con el foco.

.hamburger:is(:hover, :focus) svg > line {
  stroke: hsl(var(--brandHSL));
}

Agrégale a JavaScript

Presiona escape para cerrar

La tecla Escape del teclado debería cerrar el menú a la derecha. Vamos a cablearlo.

const sidenav = document.querySelector('#sidenav-open');

sidenav.addEventListener('keyup', event => {
  if (event.code === 'Escape') document.location.hash = '';
});
Historial del navegador

Para evitar que la interacción abierta y cerrada se apilen varios entradas al historial del navegador, agrega el siguiente JavaScript intercalado al el botón de cerrar:

<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>

Esto eliminará la entrada del historial de URL al cerrarse, lo que hará que parezca que el menú está nunca se abrió.

Enfoque en la UX

El siguiente fragmento nos ayuda a enfocarnos en los botones de apertura y cierre después de cuando se abren o cierran. Quiero que la activación o desactivación sea fácil.

sidenav.addEventListener('transitionend', e => {
  const isOpen = document.location.hash === '#sidenav-open';

  isOpen
      ? document.querySelector('#sidenav-close').focus()
      : document.querySelector('#sidenav-button').focus();
})

Cuando se abra el panel de navegación lateral, enfoca el botón de cierre. Cuando se cierra el panel de navegación lateral, enfocar el botón para abrir. Para ello, llamo a focus() en el elemento de JavaScript.

Conclusión

Ahora que sabes cómo lo hice, ¿cómo lo harías? Esto hace que la arquitectura de componentes sea divertida. ¿Quién va a hacer la 1a versión con ranuras? 🙂

Diversifiquemos nuestras diferentes enfoques y aprender todas las formas de construir en la web. Crea una falla, twittea tu versión y la agregaré a la Aquí tienes la sección de remixes de la comunidad.

Remixes de la comunidad