Descripción general básica sobre cómo crear una experiencia similar a las Historias de Instagram en la Web.
En esta publicación, quiero compartir ideas sobre cómo compilar 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 para compilar este componente de Historias por tu cuenta, consulta el codelab del componente de Historias.
Si prefieres un video, aquí tienes una versión de este artículo en YouTube:
Descripción general
Dos ejemplos populares de la UX de Historias son las Historias de Snapchat y las Historias de Instagram (sin mencionar las flotas). En términos generales de UX, las Historias suelen ser un patrón centrado en los toques y exclusivo para dispositivos móviles para navegar por varias suscripciones. Por ejemplo, en Instagram, los usuarios abren la historia de un amigo y ven 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 avanza a otro amigo. Un componente de Story es bastante similar a un carrusel, pero permite navegar por un array multidimensional en lugar de un array unidimensional. Es como si hubiera un carrusel dentro de cada carrusel. 🤯

2º carrusel "apilado" de historias
👍 Lista en una lista, también conocida como array multidimensional
Cómo elegir las herramientas adecuadas para el trabajo
En general, me resultó bastante sencillo compilar este componente gracias a algunas funciones críticas de la plataforma web. Veamos cuáles son.
Cuadrícula de CSS
Nuestro diseño no resultó ser una tarea difícil para CSS Grid, ya que está equipado con algunas formas poderosas de organizar el contenido.
Diseño de amigos
Nuestro wrapper de componente .stories
principal es una vista de desplazamiento horizontal centrada 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 ventana gráfica en dispositivos móviles con
100vh
y100vw
, y restringimos el tamaño en computadoras de escritorio. /
separa nuestras plantillas de filas y columnasauto-flow
se traduce comogrid-auto-flow: column
- La plantilla de autoflujo es
100%
, que, en este caso, es el ancho de la ventana de desplazamiento.
En un teléfono celular, piensa en esto como si el tamaño de la fila fuera la altura del viewport y cada columna fuera el ancho del viewport. Si continuamos 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 amigos continúen fuera del viewport para que tengamos dónde desplazarnos. La cuadrícula creará tantas columnas como necesite para diseñar tu HTML para cada historia de amigos, lo que creará un contenedor de desplazamiento dinámico y responsivo para nosotros. La cuadrícula nos permitió centralizar todo el efecto.
Apilamiento
Para cada amigo, necesitamos sus historias en un estado listo para la paginación. Elegí una pila para prepararme para la animación y otros patrones divertidos. Cuando digo pila, me refiero a que la mires desde arriba, como un sándwich, no desde el 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 permite que nuestro código HTML controle el orden de apilamiento y también mantiene todos los elementos en flujo. Observa que no tuvimos que hacer nada con el posicionamiento de absolute
ni con z-index
, y no tuvimos que corregir el cuadro con height: 100%
ni width: 100%
. La cuadrícula principal ya definió el tamaño de la ventana gráfica de la imagen de la historia, por lo que no fue necesario indicarle a ninguno de estos componentes de la historia que la completaran.
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 de CSS, tenías que usar JavaScript, y era… complicado, por decirlo de alguna manera. Consulta Introducing CSS Scroll Snap Points de Sarah Drasner para obtener un excelente análisis sobre cómo usarlos.
scroll-snap-points
.
Sin ella, los usuarios pueden desplazarse libremente como de costumbre. Con él, el navegador se apoya suavemente en cada elemento.
.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í Scroll Snap Points por varios motivos:
- Accesibilidad gratuita. La especificación de Scroll Snap Points indica que, de forma predeterminada, al presionar las teclas de flecha hacia la izquierda y flecha hacia la derecha, se debe avanzar por los puntos de ajuste.
- Una especificación en crecimiento: La especificación de Scroll Snap Points recibe nuevas funciones y mejoras 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 están diseñados prácticamente para el caso de uso de paginación horizontal centrada en el tacto.
- Inercia de estilo de plataforma libre. 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 extraño.
Compatibilidad entre navegadores
Realizamos pruebas en Opera, Firefox, Safari y Chrome, además de Android y iOS. A continuación, se incluye 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 actualmente algunas plataformas no tienen optimizaciones de UX. Me gustó no tener que administrar estas funciones y confío en 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 necesita detenerse en cada imagen después de que un usuario interactúa con él. Puede ser aceptable o incluso recomendable desplazarse rápidamente por el carrusel. Por otro lado, lo mejor es navegar por las historias 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 entrada del blog, scroll-snap-stop
solo se admite en navegadores basados en Chromium. Consulta Compatibilidad del navegador para obtener actualizaciones. Sin embargo, no es un bloqueo. Solo significa que, en los navegadores no compatibles, los usuarios pueden omitir a un amigo por accidente. Por lo tanto, los usuarios deberán tener más cuidado, o bien tendremos que escribir código JavaScript para asegurarnos de que un amigo omitido no se marque como visto.
Obtén más información en la especificación si te interesa.
overscroll-behavior
¿Alguna vez te desplazaste por una ventana modal y, de repente, comenzaste a desplazarte por el contenido que se encontraba detrás de ella?
overscroll-behavior
permite que el desarrollador atrape ese desplazamiento y nunca lo deje
ir. Es ideal para todo tipo de ocasiones. El componente Mis historias lo usa para evitar que los gestos adicionales de deslizamiento y desplazamiento salgan del componente.
.stories {
overflow-x: auto;
overscroll-behavior: contain;
}
Safari y Opera fueron los 2 navegadores que no admitieron esta función, y eso está bien. Esos usuarios tendrán una experiencia de desplazamiento excesivo como a la que están acostumbrados 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 excesivo 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 para que se mostrara. La compatibilidad con los conceptos básicos de esto es excelente; todos los navegadores lo desplazaron 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 del navegador para obtener actualizaciones.
Práctica
Ahora que sabes cómo lo hice, ¿cómo lo harías tú? Diversifiquemos nuestros enfoques y aprendamos todas las formas de crear en la Web. Crea un Glitch, envíame un tweet con tu versión y la agregaré a la sección Remixes de la comunidad que se encuentra más abajo.
Remixes de la comunidad
- @geoffrich_ con Svelte: demo y código
- @GauteMeekOlsen con Vue: demostración y código
- @AnaestheticsApp con Lit: demo y code