Desplazamiento bien controlado con Snap de desplazamiento de CSS

Declara posiciones de ajuste del desplazamiento para crear experiencias de desplazamiento bien controladas.

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

La función Scroll Snap de CSS permite a los desarrolladores web crear experiencias de desplazamiento bien controladas mediante la declaración de posiciones de detención del desplazamiento. Los artículos paginados y los carruseles de imágenes son dos ejemplos de esto que se usan con frecuencia. CSS Scroll Snap proporciona una API coherente y fácil de usar para compilar estos patrones de UX populares.

Segundo plano

El caso de la detención del desplazamiento

El desplazamiento es una forma popular y natural de interactuar con el contenido en la Web. Es el medio nativo de la plataforma para proporcionar acceso a más información de la que se ve en la pantalla a la vez, lo que se vuelve especialmente vital en las plataformas para dispositivos móviles con espacio de pantalla limitado. Por lo tanto, no es de extrañar que los autores web prefieran cada vez más organizar el contenido en listas planas desplazables en lugar de jerarquías profundas.

La principal desventaja del desplazamiento es su falta de precisión. Raramente un desplazamiento termina alineado con un párrafo o una oración. Esto es aún más pronunciado en el caso del contenido paginado o detallado con límites significativos cuando el desplazamiento finaliza en el medio de la página o la imagen, lo que la deja parcialmente visible. Estos casos de uso se benefician de una experiencia de desplazamiento bien controlada.

Los desarrolladores web han confiado durante mucho tiempo en soluciones basadas en JavaScript para controlar el desplazamiento y ayudar a abordar esta deficiencia. Sin embargo, las soluciones basadas en JavaScript no proporcionan una solución de fidelidad completa debido a la falta de primitivas de personalización del desplazamiento o el acceso al desplazamiento compuesto. El desplazamiento de CSS asegura una solución rápida, de alta fidelidad y fácil de usar que funciona de manera coherente en todos los navegadores.

El desplazamiento de CSS permite a los autores web marcar cada contenedor de desplazamiento con límites para las operaciones de desplazamiento en las que finalizar. Luego, los navegadores eligen la posición final más apropiada según los detalles de la operación de desplazamiento, el diseño y la visibilidad del contenedor de desplazamiento, y los detalles de las posiciones de ajuste, y luego se animan de forma fluida. Volvamos a nuestro ejemplo anterior. Cuando el usuario termina de desplazar el carrusel, su imagen visible se ajusta en su lugar. JavaScript no necesita ajustes de desplazamiento.

Ejemplo de uso de la detención de desplazamiento de CSS con un carrusel de imágenes.
Ejemplo del uso de la función de ajuste de desplazamiento de CSS con un carrusel de imágenes. Aquí, el ajuste del desplazamiento garantiza que, al final del desplazamiento, el centro horizontal de una imagen esté alineado con el centro horizontal del contenedor de desplazamiento.

CSS Scroll Snap

El ajuste del desplazamiento consiste en ajustar el desplazamiento de un contenedor de desplazamiento para que esté en una posición de ajuste preferida una vez que finalice la operación de desplazamiento.

Se puede habilitar el ajuste del desplazamiento de un contenedor de desplazamiento con la propiedad scroll-snap-type. Esto le indica al navegador que debe considerar ajustar este contenedor de desplazamiento a las posiciones de ajuste que producen sus elementos secundarios. scroll-snap-type determina el eje en el que se produce el desplazamiento: x, y o both, y la rigidez del ajuste: mandatory, proximity. Más adelante, hablaremos sobre esto.

Para producir una posición de ajuste, declara una alineación deseada en un elemento. Esta posición es el desplazamiento en el que el contenedor de desplazamiento superior más cercano y el elemento están alineados como se especifica para el eje determinado. En cada eje, se pueden usar las siguientes alineaciones: start, end, center.

Una alineación start significa que el borde de inicio del puerto de ajuste del contenedor de desplazamiento debe alinearse con el borde de inicio del área de ajuste del elemento. De manera similar, las alineaciones end y center significan que el borde final o el centro del puerto de ajuste del contenedor de desplazamiento deben alinearse con el borde final o el centro del área de ajuste del elemento.

Ejemplo de varias alineaciones en el eje de desplazamiento horizontal.

En los siguientes ejemplos, se muestra cómo usar estos conceptos.

Un caso de uso común para el ajuste del desplazamiento es un carrusel de imágenes. Por ejemplo, para crear un carrusel de imágenes horizontal que se ajuste a cada imagen a medida que te desplazas, podemos especificar que el contenedor de desplazamiento tenga un scroll-snap-type obligatorio en el eje horizontal. Establece cada imagen en scroll-snap-align: center para asegurarte de que el ajuste centre la imagen dentro del carrusel.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

Debido a que las posiciones de ajuste están asociadas con un elemento, el algoritmo de ajuste puede ser inteligente sobre cuándo y cómo se ajusta según el elemento y el tamaño del contenedor de desplazamiento. Por ejemplo, considera el caso en el que una imagen es más grande que el carrusel. Un algoritmo de ajuste ingenuo puede impedir que el usuario se desplace para ver la imagen completa. Sin embargo, la especificación requiere que las implementaciones detecten este caso y permitan que el usuario se desplace libremente dentro de esa imagen solo ajustando sus bordes.

Ver demostración | Fuente

Ejemplo: Una página de producto con recorrido

Otro caso común que puede beneficiarse del ajuste del desplazamiento son las páginas con varias secciones lógicas para desplazarse verticalmente, por ejemplo, una página de producto típica. scroll-snap-type: y proximity; es una opción más natural para casos como este. No interfiere cuando un usuario se desplaza hasta la mitad de una sección en particular, pero también se ajusta y llama la atención a una sección nueva cuando se desplaza lo suficientemente cerca.

A continuación, te mostramos cómo hacerlo:

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

Padding y margen de desplazamiento

La página del producto tiene un encabezado superior de posición fija. El diseño también pedía que parte de la sección superior permaneciera visible cuando el contenedor de desplazamiento se ajustara para proporcionarles a los usuarios una indicación de diseño sobre el contenido anterior.

La propiedad scroll-padding es una nueva propiedad CSS que se puede usar para ajustar la región visible efectiva del contenedor de desplazamiento o el punto de ajuste, que se usa cuando se calculan las alineaciones de ajuste del desplazamiento. La propiedad define un inserto contra el cuadro de padding del contenedor de desplazamiento. En nuestro ejemplo, se agregó un inset adicional de 15vh a la parte superior, lo que le indica al navegador que considere una posición más baja, 15vh debajo del borde superior del contenedor de desplazamiento, como su borde de inicio vertical para el ajuste del desplazamiento. Cuando se aplique el ajuste, el borde inicial del elemento de destino de ajuste se alineará con esta nueva posición, lo que dejará espacio arriba.

La propiedad scroll-margin define el importe inicial que se usa para ajustar el cuadro efectivo del objetivo de ajuste de manera similar a la forma en que scroll-padding funciona en el contenedor de desplazamiento de ajuste.

Es posible que hayas notado que estas dos propiedades no tienen la palabra "snap". Esto es intencional, ya que en realidad modifican el cuadro para todas las operaciones de desplazamiento relevantes y no solo ajustan el desplazamiento. Por ejemplo, Chrome los tiene en cuenta cuando calcula el tamaño de la página para las operaciones de desplazamiento de paginación, como PageDown y PageUp, y también cuando calcula el importe de desplazamiento para la operación Element.scrollIntoView().

Ver demostración | Fuente

Interacción con otras APIs de desplazamiento

API de DOM Scrolling

El ajuste del desplazamiento se produce después de todas las operaciones de desplazamiento, incluidas las que inicia la secuencia de comandos. Cuando uses APIs como Element.scrollTo, el navegador calculará la posición de desplazamiento prevista de la operación y, luego, aplicará la lógica de ajuste adecuada para encontrar la ubicación final ajustada. Por lo tanto, no es necesario que la secuencia de comandos del usuario realice ningún cálculo manual para ajustarse.

Desplazamiento fluido

El desplazamiento suave controla el comportamiento de una operación de desplazamiento programática, mientras que el ajuste del desplazamiento determina su destino. Dado que controlan aspectos ortogonales del desplazamiento, se pueden usar en conjunto y complementarse.

Comportamiento de sobredesplazamiento

La API de comportamiento de desplazamiento excesivo controla cómo se encadena el desplazamiento en varios elementos y no se ve afectado por el ajuste del desplazamiento.

Consideraciones y prácticas recomendadas

Evita usar la alineación obligatoria cuando los elementos de destino estén muy separados. Esto puede hacer que el contenido entre las posiciones de ajuste sea inaccesible.

En muchos casos, el ajuste del desplazamiento se puede agregar como una mejora sin necesidad de detectar componentes. Si es necesario, usa @supports o CSS.supports para detectar la compatibilidad con CSS Scroll Snap. Evita usar scroll-snap-type, que también está presente en la especificación obsoleta.

Detección de funciones en CSS

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

Detección de funciones en JavaScript

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

No supongas que las APIs de desplazamiento programático, como Element.scrollTo, siempre terminan en el desplazamiento desplazado solicitado. El ajuste del desplazamiento puede ajustar el desplazamiento después de que se complete el desplazamiento programático. Ten en cuenta que esta no era una buena suposición incluso antes del ajuste del desplazamiento, ya que el desplazamiento podría haberse interrumpido por otros motivos, pero esto es especialmente el caso del ajuste del desplazamiento.

Trabajo futuro

La experiencia de desplazamiento fue el tema de una encuesta reciente del equipo de Chrome. Los resultados de la encuesta identificaron varias áreas que necesitan trabajo adicional para reducir la brecha entre las bibliotecas de complementos y el CSS. El trabajo próximo se enfocará en scroll-snap, lo que incluye lo siguiente:

  1. Disponibilidad y compatibilidad de la API en todos los navegadores
  2. Trabaja en nuevas APIs de CSS, como scroll-start.
  3. Trabaja en eventos JS nuevos, como snapChanged().