Cómo compilar un componente de desplazamiento multimedia

Una descripción general fundamental de cómo crear una vista de desplazamiento horizontal responsiva para TVs, teléfonos, computadoras, etcétera.

En esta publicación, quiero compartir algunas ideas sobre formas de crear experiencias de desplazamiento horizontal para la Web que sean mínimas, responsivas, accesibles y funcionen en diferentes navegadores y plataformas (como las TVs). Prueba la demostración.

Demostración

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

Descripción general

Crearemos un diseño de desplazamiento horizontal para alojar miniaturas de contenido multimedia o productos. El componente comienza como una lista <ul> sencilla, pero se transforma con CSS en una experiencia de desplazamiento satisfactoria y fluida, que muestra imágenes y las ajusta a una cuadrícula. Se agrega JavaScript para facilitar las interacciones de índice móvil, lo que ayuda a los usuarios de teclado a omitir más de 100 elementos. Además, se usa una consulta de medios experimental, prefers-reduced-data, para convertir la barra de desplazamiento de contenido multimedia en una experiencia ligera de desplazamiento por el título.

Comienza con lenguaje de marcado accesible

Un desplazador multimedia consta de solo un par de componentes principales, una lista con elementos. Una lista, en su forma más simple, puede viajar por todo el mundo y todos pueden consumirla claramente. Un usuario que llega a esta página puede explorar una lista y hacer clic en un vínculo para ver un elemento. Esta es nuestra base accesible.

Publica una lista con un elemento <ul>:

<ul class="horizontal-media-scroller">
  <li></li>
  <li></li>
  <li></li>
  ...
<ul>

Haz que los elementos de la lista sean interactivos con un elemento <a>:

<li>
  <a href="#">
    ...
  </a>
</li>

Usa un elemento <figure> para representar de manera semántica una imagen y su leyenda:

<figure>
  <picture>
    <img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
  </picture>
  <figcaption>Legends</figcaption>
</figure>

Observa los atributos alt y loading en el <img>. El texto alternativo para un desplazador multimedia es una oportunidad de UX que ayuda a brindar contexto adicional a la miniatura o como texto de resguardo si la imagen no se cargó, o bien proporciona una IU hablada para los usuarios que dependen de la tecnología de accesibilidad, como un lector de pantalla. Obtén más información en Cinco reglas de oro para crear texto alternativo compatible.

El atributo loading acepta la palabra clave lazy como una forma de indicar que se debe recuperar esta fuente de imágenes solo cuando la imagen está dentro del viewport. Esto puede ser muy útil para listas grandes, ya que los usuarios solo descargarán imágenes de los elementos que se desplazaron para visualizar.

Cómo admitir la preferencia de esquema de colores del usuario

Usa color-scheme como una etiqueta <meta> para indicar al navegador que tu página quiere los estilos de usuario-agente claro y oscuro. Puedes ver el modo oscuro o claro, según cómo lo mires:

<meta name="color-scheme" content="dark light">

La metaetiqueta proporciona la señal más temprana posible, de modo que el navegador puede seleccionar un color oscuro predeterminado de lienzo si el usuario tiene una preferencia de tema oscuro. Esto significa que las navegaciones entre las páginas del sitio no mostrarán un fondo blanco entre las cargas. Tema oscuro fluido entre las cargas, mucho más agradable para los ojos.

Obtén más información de Thomas Steiner en https://web.dev/color-scheme/.

Agrega contenido

Dada la estructura de contenido anterior de ul > li > a > figure > picture > img, la siguiente tarea es agregar imágenes y títulos para desplazarse. Agregué la demostración con imágenes y texto de marcadores de posición estáticos, pero puedes potenciarlo desde tu fuente de datos favorita.

Agrega estilo con CSS

Ahora es el momento de que CSS tome esta lista genérica de contenido y la convierta en una experiencia. Netflix, las tiendas de aplicaciones y muchos otros sitios y apps usan áreas de desplazamiento horizontal para empaquetar el viewport con categorías y opciones.

Cómo crear el diseño de desplazamiento

Es importante evitar cortar el contenido en los diseños o recurrir al truncamiento del texto con puntos suspensivos. Muchos televisores tienen desplazadores de contenido multimedia como este, pero a menudo recurren a contenido en elipsis. Este diseño no. También permite que el contenido multimedia anule el tamaño de la columna, lo que hace que 1 diseño sea lo suficientemente flexible como para manejar muchas combinaciones interesantes.

Se muestran 2 filas con desplazamiento. Uno no tiene puntos suspensivos, lo que significa que es más alto y cada título es totalmente legible. El otro es más corto y muchos títulos están cortados con puntos suspensivos.

El contenedor permite anular el tamaño de la columna, ya que proporciona el tamaño predeterminado como una propiedad personalizada. Este diseño de cuadrícula se basa en el tamaño de la columna y solo administra el espaciado y la dirección:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2); /* parent owned value for children to be relative to*/
  margin: 0;
}

Luego, el elemento <picture> usa la propiedad personalizada para crear nuestra relación de aspecto base: un cuadro:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  & picture {
    inline-size: var(--size);
    block-size: var(--size);
  }
}

Con solo unos pocos estilos menores, completa los aspectos básicos de la barra de desplazamiento de medios:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  & > li {
    display: inline-block; /* removes the list-item bullet */
  }

  & picture {
    inline-size: var(--size);
    block-size: var(--size);
  }
}

Si configuras overflow, se configura el <ul> arriba para permitir el desplazamiento y la navegación con el teclado por toda la lista. Luego, se quitará el elemento <li> de cada elemento secundario directo ::marker mediante la obtención de un nuevo tipo de pantalla inline-block.

Sin embargo, las imágenes aún no responden y salen de la caja en la que están dentro. Domina algunos tamaños, ajustes y estilos de borde, además de un gradiente de fondo para cuando sean de carga diferida:

img {
  /* smash into whatever box it's in */
  inline-size: 100%;
  block-size: 100%;

  /* don't squish but do cover the space */
  object-fit: cover;

  /* soften the edges */
  border-radius: 1ex;
  overflow: hidden;

  /* if empty, show a gradient placeholder */
  background-image:
    linear-gradient(
      to bottom,
      hsl(0 0% 40%),
      hsl(0 0% 20%)
    );
}

Relleno de desplazamiento

La alineación con el contenido de la página, además de un área de superficie de desplazamiento de borde a borde, son esenciales para un componente armonioso y mínimo.

Para lograr el diseño de desplazamiento de borde a borde que se alinea con nuestra tipografía y nuestras líneas de diseño, usa padding que coincida con scroll-padding:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  padding-inline: var(--gap);
  scroll-padding-inline: var(--gap);
  padding-block: calc(var(--gap) / 2); /* make space for scrollbar and focus outline */
}

Corrección de errores relacionados con el padding horizontal de desplazamiento Lo anterior muestra lo fácil que debería ser rellenar un contenedor de desplazamiento, pero tiene problemas de compatibilidad excepcionales (aunque se corrigieron en Chromium 91 y versiones posteriores). Consulta aquí para ver un poco del historial, pero la versión breve indica que el padding no siempre se tuvo en cuenta en una vista de desplazamiento.

Se destaca un cuadro en el extremo intercalado del último elemento de la lista, lo que muestra que el padding y el elemento tienen el mismo ancho que para crear la alineación deseada.

Para engañar a los navegadores a fin de que coloquen el padding al final de la barra de desplazamiento, enfocaré la última figura de cada lista y agregaré un seudoelemento que sea la cantidad de padding deseada.

.horizontal-media-scroller > li:last-of-type figure {
  position: relative;

  &::after {
    content: "";
    position: absolute;

    inline-size: var(--gap);
    block-size: 100%;

    inset-block-start: 0;
    inset-inline-end: calc(var(--gap) * -1);
  }
}

El uso de propiedades lógicas permite que el desplazador multimedia funcione en cualquier modo de escritura y dirección del documento.

Ajustes de desplazamiento

Un contenedor de desplazamiento con desbordamiento puede convertirse en un viewport de ajuste con una línea de CSS. Luego, depende de elementos secundarios para especificar cómo desean alinearse con ese viewport.

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  padding-inline: var(--gap);
  scroll-padding-inline: var(--gap);
  padding-block-end: calc(var(--gap) / 2);

  scroll-snap-type: inline mandatory;

  & figure {
    scroll-snap-align: start;
  }
}

Enfoque

La inspiración de este componente proviene de su gran popularidad en TVs, en App Stores y muchos otros lugares. Muchas plataformas de videojuegos usan un desplazador multimedia muy similar a este, como diseño de pantalla principal principal. Aquí, el enfoque es un gran momento de experiencia de usuario, no solo una pequeña adición. Imagina que usas este desplazador multimedia desde tu sofá con un control remoto, agrega algunas pequeñas mejoras a esa interacción:

.horizontal-media-scroller a {
  outline-offset: 12px;

  &:focus {
    outline-offset: 7px;
  }

  @media (prefers-reduced-motion: no-preference) {
    & {
      transition: outline-offset .25s ease;
    }
  }
}

De esta manera, se establece el estilo del esquema de enfoque 7px fuera del cuadro, lo que le da un espacio agradable. Si el usuario no tiene preferencias de movimiento para reducir el movimiento, se realiza una transición del desplazamiento y se proporciona un movimiento sutil al evento de enfoque.

Índice móvil

Los usuarios de controles de juegos y teclados necesitan atención especial en estas largas listas de opciones y contenido con desplazamiento. El patrón común para resolver esto se denomina índice de migración. Ocurre cuando un contenedor de elementos está enfocado en el teclado, pero solo se le permite a 1 elemento secundario mantener el enfoque a la vez. Este único elemento enfocable a la vez está diseñado para permitir omitir la lista potencialmente larga de elementos, en lugar de presionar la tecla Tab más de 50 veces para llegar al final.

Hay 300 elementos en ese primer desplazador de la demostración. Podemos hacerlo mejor que hacer que los atraviesen a todos para llegar a la siguiente sección.

Para crear esta experiencia, JavaScript necesita observar los eventos de teclado y de enfoque. Creé una pequeña biblioteca de código abierto en npm para ayudar a que esta experiencia del usuario sea fácil de lograr. A continuación, te indicamos cómo utilizarlo para los 3 desplazadores:

import {rovingIndex} from 'roving-ux';

rovingIndex({
  element: someElement
});

En esta demostración, se consulta el documento para los desplazadores y, para cada una de ellas, se llama a la función rovingIndex(). Pasa el elemento rovingIndex() para obtener la experiencia móvil, como un contenedor de listas y un selector de consultas de destino, en caso de que los objetivos de enfoque no sean subordinados directos.

document.querySelectorAll('.horizontal-media-scroller')
  .forEach(scroller =>
    rovingIndex({
      element: scroller,
      target: 'a',
}))

Para obtener más información sobre este efecto, consulta la biblioteca de código abierto roving-ux.

Relación de aspecto

Al momento de escribir esta publicación, la compatibilidad con aspect-ratio está detrás de una marca en Firefox, pero está disponible en los navegadores Chromium o los decodificadores. Dado que el diseño de cuadrícula del desplazamiento multimedia solo especifica la dirección y el espaciado, el tamaño puede cambiar dentro de una consulta de medios que verifica la compatibilidad con la relación de aspecto. Mejora progresiva en algunos desplazadores de contenido multimedia más dinámicos

Se muestra un cuadro con una relación de aspecto de 4:4 junto a las demás relaciones de diseño utilizadas de 16:9 y 4:3.

@supports (aspect-ratio: 1) {
  .horizontal-media-scroller figure > picture {
    inline-size: auto; /* for a block-size driven ratio */
    aspect-ratio: 1; /* boxes by default */

    @nest section:nth-child(2) & {
      aspect-ratio: 16/9;
    }

    @nest section:nth-child(3) & {
      /* double the size of the others */
      block-size: calc(var(--size) * 2);
      aspect-ratio: 4/3;

      /* adjust size to fit more items into the viewport */
      @media (width <= 480px) {
        block-size: calc(var(--size) * 1.5);
      }
    }
  }
}

Si el navegador admite la sintaxis aspect-ratio, las imágenes del desplazador multimedia se actualizan al tamaño aspect-ratio. Con la sintaxis de anidación de borradores, cada imagen cambia su relación de aspecto según si es la primera, segunda o tercera fila. La sintaxis de Nest también permite establecer algunos ajustes pequeños del viewport, directamente con la otra lógica de tamaño.

Con ese CSS, a medida que la función esté disponible en más motores de navegador, se renderizará un diseño más atractivo, fácil de administrar y visualmente atractivo.

Prefiere datos reducidos.

Si bien la siguiente técnica solo está disponible detrás de una marca en Canary, quería compartirte cómo ahorrar una cantidad considerable de tiempo de carga de la página y uso de datos con unas pocas líneas de CSS. La consulta multimedia prefers-reduced-data del nivel 5 permite preguntar si el dispositivo se encuentra en estados de datos reducidos, como el modo de Ahorro de datos. Si es así, puedo modificar el documento y, en este caso, ocultar las imágenes.

ALT_TEXT_HERE

figure {
  @media (prefers-reduced-data: reduce) {
    & {
      min-inline-size: var(--size);

      & > picture {
        display: none;
      }
    }
  }
}

El contenido aún es navegable, pero sin el costo de descargar imágenes pesadas. Este es el sitio antes de agregar el CSS prefers-reduced-data:

(7 solicitudes, 100 KB de recursos en 131 ms)

ALT_TEXT_HERE

Este es el rendimiento del sitio después de agregar el CSS prefers-reduced-data:

ALT_TEXT_HERE

(71 solicitudes, 1.2 MB de recursos en 1.07 s)

64 solicitudes menos, serían las aproximadamente 60 imágenes dentro del viewport (pruebas realizadas en una pantalla panorámica) de esta pestaña del navegador, un aumento de la carga de la página de aproximadamente el 80% y el 10% de los datos por cable. CSS bastante poderoso.

Conclusión

Ahora que sabes cómo lo hice, ¿cómo lo harías? 🙂

Diversifiquemos nuestros enfoques y aprendamos todas las formas de desarrollar en la Web. Crea una Codepen o aloja tu propia demostración, twittea con ella y la agregaré a la sección de remixes de la comunidad a continuación.

Origen

Remixes de la comunidad

Aún no hay nada que ver aquí.