Desplazamiento bien controlado con Snap de desplazamiento de CSS

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

La función Ajuste de desplazamiento de CSS permite que los desarrolladores web creen experiencias de desplazamiento bien controladas declarando posiciones de ajuste de desplazamiento. Los artículos paginados y los carruseles de imágenes son dos ejemplos de uso frecuente. El ajuste de desplazamiento de CSS proporciona una API coherente y fácil de usar para crear estos patrones de UX populares.

Fondo

El caso del ajuste de 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 puede ver 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. Rara vez un desplazamiento termina alineado con un párrafo o una oración. Esto es aún más pronunciado para el contenido paginado o detallado con límites significativos cuando el desplazamiento finaliza en el medio de la página o imagen, lo que lo 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 solucionar 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 de desplazamiento o acceso al desplazamiento compuesto. El ajuste de desplazamiento de CSS garantiza una solución rápida, de alta fidelidad y fácil de usar que funciona de manera coherente en todos los navegadores.

El ajuste de desplazamiento de CSS permite que los autores web marquen cada contenedor de desplazamiento con límites para las operaciones de desplazamiento en las que se debe finalizar. Luego, los navegadores eligen la posición final más adecuada según las características 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. Volviendo a nuestro ejemplo anterior, cuando el usuario termina de desplazarse por el carrusel, la imagen visible se ajusta en su lugar. No se necesitan ajustes de desplazamiento con JavaScript.

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

Ajuste de desplazamiento de CSS

El ajuste de desplazamiento es el acto de 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 de desplazamiento en 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 producidas por sus descendientes. scroll-snap-type determina el eje en el que se produce el desplazamiento: x, y o both, y el rigor de ajuste: mandatory, proximity. Más adelante, hablaremos sobre estos temas.

Se puede producir una posición de ajuste declarando una alineación deseada en un elemento. Esta posición es el desplazamiento de la barra de desplazamiento en el que el contenedor de desplazamiento principal más cercano y el elemento se alinean según lo especificado para el eje determinado. Las siguientes alineaciones son posibles en cada eje: start, end, center.

Una alineación start significa que el borde de inicio del puerto de ajuste del contenedor de desplazamiento debe estar alineado con el borde de inicio del área de ajuste del elemento. Del mismo modo, las alineaciones end y center significan que el borde o el centro del puerto de ajuste del contenedor de desplazamiento deben alinearse con el borde o el centro del área de ajuste del elemento.

Ejemplo de varias alineaciones en el eje de desplazamiento horizontal.

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

Un caso de uso común para el ajuste de 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 implementaciones para detectar este caso y permitir que el usuario se desplace libremente dentro de esa imagen solo ajustándose a sus bordes.

Ejemplo: Una página de producto con un recorrido

Otro caso común que puede beneficiarse del ajuste de 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 más natural para casos como este. No interfiere cuando un usuario se desplaza hasta el medio de una sección en particular, pero también se ajusta y llama la atención sobre una sección nueva cuando se desplaza lo suficientemente cerca.

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

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 requería que parte de la sección superior permaneciera visible cuando se ajustara el contenedor de desplazamiento para proporcionar una indicación de diseño a los usuarios sobre el contenido de arriba.

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

La propiedad scroll-margin define la cantidad de margen exterior que se usa para ajustar el cuadro efectivo del objetivo de ajuste, de forma similar a como funciona scroll-padding en el contenedor de desplazamiento de ajuste.

Es posible que hayas notado que estas dos propiedades no tienen la palabra "snap" en ellas. Esto es intencional, ya que modifican el cuadro para todas las operaciones de desplazamiento relevantes y no solo para el ajuste de desplazamiento. Por ejemplo, Chrome las 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 la cantidad de desplazamiento para la operación Element.scrollIntoView().

Interacción con otras APIs de desplazamiento

API de desplazamiento del DOM

El ajuste de desplazamiento se produce después de todas las operaciones de desplazamiento, incluidas las que se inician con una secuencia de comandos. Cuando usas APIs como Element.scrollTo, el navegador calcula la posición de desplazamiento prevista de la operación y, luego, aplica 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 cálculos manuales para la alineación.

Desplazamiento fluido

El desplazamiento fluido controla el comportamiento de una operación de desplazamiento programática, mientras que el ajuste de desplazamiento determina su destino. Como controlan aspectos ortogonales del desplazamiento, se pueden usar juntos y complementarse entre sí.

Comportamiento de sobredesplazamiento

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

Advertencias 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 se vuelva inaccesible.

En muchos casos, el ajuste de desplazamiento se puede agregar como una mejora sin necesidad de detectar funciones. Si es necesario, usa @supports o CSS.supports para detectar la compatibilidad con el ajuste de desplazamiento de CSS. 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 solicitado. El ajuste de desplazamiento puede modificar 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 de desplazamiento, ya que el desplazamiento podría haberse interrumpido por otros motivos, pero es especialmente el caso con el ajuste de desplazamiento.

Trabajo futuro

La experiencia de desplazamiento fue el tema central 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 CSS. El trabajo próximo se centrará en scroll-snap, lo que incluye lo siguiente:

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