Una descripción general fundamental de cómo crear una experiencia similar a las Historias de Instagram en la Web.
En esta publicación, quiero compartir mis ideas sobre la compilación de un componente de Historias para la Web que sea responsivo, admita la navegación con el teclado y funcione en todos los navegadores.
Si prefieres una demostración práctica de cómo compilar este componente de Historias por tu cuenta, consulta el codelab del componente de Historias.
Si prefieres ver un video, aquí tienes una versión de esta publicación en YouTube:
Descripción general
Dos ejemplos populares de la UX de las Historias son las Historias de Snapchat y las de Instagram (sin mencionar las flotas). En términos generales de UX, las historias suelen ser un patrón centrado en la presión solo para dispositivos móviles para navegar por varias suscripciones. Por ejemplo, en Instagram, los usuarios abren la historia de un amigo y revisan las fotos que contiene. Por lo general, lo hacen con muchos amigos a la vez. Si presiona el lado derecho del dispositivo, el usuario avanza a la siguiente historia de ese amigo. Si desliza el dedo hacia la derecha, el usuario pasa a otro amigo. Un componente de historia es bastante similar a un carrusel, pero permite navegar por un array multidimensiona en lugar de uno unidimensional. Es como si hubiera un carrusel dentro de cada carrusel. 🤯
Elige las herramientas adecuadas para el trabajo
En general, encontré que este componente es bastante sencillo de compilar, gracias a algunas funciones críticas de la plataforma web. Analicemos cada una de ellas.
Cuadrícula de CSS
Nuestro diseño no fue un gran desafío para CSS Grid, ya que está equipado con algunas formas potentes de controlar el contenido.
Diseño de Amigos
Nuestro wrapper de componentes .stories
principal es un ScrollView horizontal centrado en dispositivos móviles:
.stories {
inline-size: 100vw;
block-size: 100vh;
display: grid;
grid: 1fr / auto-flow 100%;
gap: 1ch;
overflow-x: auto;
scroll-snap-type: x mandatory;
overscroll-behavior: contain;
touch-action: pan-x;
}
/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
max-inline-size: 480px;
max-block-size: 848px;
}
Desglosemos ese diseño grid
:
- Completamos explícitamente la vista del puerto en dispositivos móviles con
100vh
y100vw
, y restringimos el tamaño en computadoras de escritorio. /
separa nuestras plantillas de filas y columnas.auto-flow
se traduce comogrid-auto-flow: column
- La plantilla de flujo automático es
100%
, que en este caso es el ancho de la ventana de desplazamiento.
En un teléfono celular, imagina que el tamaño de la fila es la altura del viewport y cada columna es el ancho del viewport. Siguiendo con el ejemplo de las Historias de Snapchat y las Historias de Instagram, cada columna será la historia de un amigo. Queremos que las historias de los amigos continúen fuera del viewport para que tengamos un lugar al que desplazarnos. La cuadrícula creará tantas columnas como necesite para diseñar tu código HTML para cada historia de amigo, lo que creará un contenedor de desplazamiento dinámico y responsivo. La cuadrícula nos permitió centralizar todo el efecto.
Apilamiento
Para cada amigo, necesitamos que sus historias estén en un estado listo para la paginación. En preparación para la animación y otros patrones divertidos, elegí una pila. Cuando digo apilar, me refiero a que es como si estuvieras mirando hacia abajo un sandwich, no como si lo miraras de costado.
Con la cuadrícula de CSS, podemos definir una cuadrícula de una sola celda (es decir, un cuadrado), en la que las filas y las columnas comparten un alias ([story]
) y, luego, cada elemento secundario se asigna a ese espacio de una sola celda con alias:
.user {
display: grid;
grid: [story] 1fr / [story] 1fr;
scroll-snap-align: start;
scroll-snap-stop: always;
}
.story {
grid-area: story;
background-size: cover;
…
}
Esto pone nuestro código HTML en control del orden de apilamiento y también mantiene todos los elementos en flujo. Observa que no tuvimos que hacer nada con el posicionamiento absolute
ni z-index
, ni tampoco tuvimos que corregir el cuadro con height: 100%
o width: 100%
. La cuadrícula superior ya definió el tamaño de la vista de la imagen de la historia, por lo que no se necesitó decirle a ninguno de estos componentes de la historia que la ocupe.
Puntos de ajuste de desplazamiento de CSS
La especificación de puntos de ajuste de desplazamiento de CSS facilita el bloqueo de elementos en el viewport durante el desplazamiento. Antes de que existieran estas propiedades CSS, debías usar JavaScript, y era… complicado, por decir lo menos. Consulta Introducing CSS Scroll Snap Points de Sarah Drasner para obtener un excelente desglose de cómo usarlos.
.stories { display: grid; grid: 1fr / auto-flow 100%; gap: 1ch; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior: contain; touch-action: pan-x; }
.user { display: grid; grid: [story] 1fr / [story] 1fr; scroll-snap-align: start; scroll-snap-stop: always; }
Elegí los puntos de ajuste de desplazamiento por varios motivos:
- Accesibilidad gratuita. La especificación de puntos de ajuste del desplazamiento indica que presionar las teclas Flecha hacia la izquierda y Flecha hacia la derecha debería desplazarte por los puntos de ajuste de forma predeterminada.
- Especificación en crecimiento: La especificación de puntos de ajuste de desplazamiento recibe funciones y mejoras nuevas todo el tiempo, lo que significa que mi componente de Historias probablemente solo mejorará a partir de ahora.
- Facilidad de implementación. Los puntos de ajuste de desplazamiento se compilan prácticamente para el caso de uso de paginación horizontal centrado en la función táctil.
- Inercia libre al estilo de la plataforma: Cada plataforma se desplazará y se detendrá según su estilo, a diferencia de la inercia normalizada, que puede tener un estilo de desplazamiento y detención inusual.
Compatibilidad entre navegadores
Realizamos pruebas en Opera, Firefox, Safari y Chrome, además de Android y iOS. Aquí tienes un breve resumen de las funciones web en las que encontramos diferencias en las capacidades y la compatibilidad.
Sin embargo, algunos CSS no se aplicaron, por lo que algunas plataformas no cuentan con optimizaciones de UX. Disfruté no tener que administrar estas funciones y creo que, con el tiempo, llegarán a otros navegadores y plataformas.
scroll-snap-stop
Los carruseles fueron uno de los principales casos de uso de UX que impulsaron la creación de la especificación de puntos de ajuste de desplazamiento de CSS. A diferencia de las historias, un carrusel no siempre tiene que detenerse en cada imagen después de que un usuario interactúa con él. Es posible que sea conveniente o se recomiende hacer un recorrido rápido por el carrusel. Por otro lado, las historias se navegan mejor de a una, y eso es exactamente lo que proporciona scroll-snap-stop
.
.user {
scroll-snap-align: start;
scroll-snap-stop: always;
}
En el momento de escribir esta publicación, scroll-snap-stop
solo es compatible con los navegadores basados en Chromium. Consulta Compatibilidad con navegadores para obtener actualizaciones. Sin embargo, no es un bloqueador. Solo significa que, en los navegadores no compatibles, los usuarios pueden omitir accidentalmente a un amigo. Por lo tanto, los usuarios deberán tener más cuidado, o bien tendremos que escribir JavaScript para asegurarnos de que un amigo o amiga omitido no se marque como visto.
Obtén más información en las especificaciones si te interesa.
overscroll-behavior
¿Alguna vez te desplazaste por un diálogo modal y, de repente,
comenzaste a desplazar el contenido detrás del diálogo?
overscroll-behavior
le permite al desarrollador atrapar ese desplazamiento y nunca dejarlo. Es ideal para todo tipo de ocasiones. El componente Mis historias lo usa para evitar que los gestos de deslizamiento y desplazamiento adicionales salgan del componente.
.stories {
overflow-x: auto;
overscroll-behavior: contain;
}
Safari y Opera fueron los 2 navegadores que no admitían esta función, y eso está bien. Esos usuarios tendrán una experiencia de desplazamiento horizontal como de costumbre y es posible que nunca noten esta mejora. Personalmente, soy un gran fan y me gusta incluirlo como parte de casi todas las funciones de desplazamiento horizontal que implemento. Es una adición inofensiva que solo puede mejorar la UX.
scrollIntoView({behavior: 'smooth'})
Cuando un usuario toca o hace clic y llega al final del conjunto de historias de un amigo, es hora de pasar al siguiente amigo en el conjunto de puntos de ajuste de desplazamiento. Con JavaScript, pudimos hacer referencia al siguiente amigo y solicitar que se desplazara hasta que apareciera en la vista. La compatibilidad con los conceptos básicos es excelente; todos los navegadores lo desplazaron hasta que estuvo a la vista. Sin embargo, no todos los navegadores lo hicieron 'smooth'
. Esto solo significa que se desplazó hasta la vista en lugar de ajustarse.
element.scrollIntoView({
behavior: 'smooth'
})
Safari era el único navegador que no admitía behavior: 'smooth'
aquí. Consulta Compatibilidad con navegadores para obtener actualizaciones.
Práctica
Ahora que sabes cómo lo hice, ¿cómo lo harías? Diversifiquemos nuestros enfoques y aprendamos todas las formas de compilar en la Web. Crea un Glitch, tuitea tu versión y la agregaré a la sección Remixes de la comunidad a continuación.
Remixes de la comunidad
- @geoffrich_ con Svelte: demo y código
- @GauteMeekOlsen con Vue: demo + código
- @AnaestheticsApp con Lit: demo y código