Desplazamiento bien controlado con Snap de desplazamiento de CSS

Crea experiencias de desplazamiento bien controladas mediante la declaración de posiciones de ajuste de desplazamiento.

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

La función Ajuste de desplazamiento de CSS permite a los desarrolladores web crear experiencias de desplazamiento bien controladas mediante la declaración de posiciones de ajuste de desplazamiento. Los artículos paginados y los carruseles de imágenes son dos ejemplos de esto que se usan con frecuencia. El Snap de desplazamiento de CSS 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.

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

Durante mucho tiempo, los desarrolladores web confiaron en soluciones basadas en JavaScript para controlar el desplazamiento y solucionar esta deficiencia. Sin embargo, las soluciones basadas en JavaScript no proporcionan una solución de fidelidad total 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 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 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 animan sin problemas. Si volvemos al ejemplo anterior, cuando el usuario termina de desplazarse por el carrusel, la imagen visible se ajusta en su lugar. JavaScript no necesita ajustes de desplazamiento.

Ejemplo del uso de instantáneas 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.

Ajuste de desplazamiento de CSS

El ajuste del desplazamiento es el acto de ajustar el desplazamiento de un contenedor de desplazamiento para que se encuentre en una posición de ajuste preferida una vez que finaliza la operación de desplazamiento.

Un contenedor de desplazamiento se puede habilitar para el ajuste de desplazamiento mediante 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 subordinados. scroll-snap-type determina el eje en el que se produce el desplazamiento: x, y o both, y la rigidez del ajuste: mandatory, proximity. Hablaremos sobre esto más adelante.

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 principal más cercano y el elemento se alinean, como se especifica para el eje determinado. En cada eje, se pueden usar las siguientes alineaciones: start, end, center.

Una alineación de start significa que el borde de inicio del ajuste del contenedor de desplazamiento debe limpiarse con el borde inicial del área de ajuste del elemento. De manera similar, las alineaciones end y center implican que el borde o el centro del ajuste final del contenedor de desplazamiento debe limpiarse 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. Configura cada imagen en scroll-snap-align: center para garantizar 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>

Dado 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 en 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 propiedad de CSS nueva que se puede usar para ajustar la región visible efectiva del contenedor de desplazamiento, o Snapport, que se usa para calcular las alineaciones de ajuste de desplazamiento. La propiedad define una inserción en 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. Durante el ajuste, el borde de inicio del elemento de destino de ajuste se limpiará con esta nueva posición y dejará espacio por encima.

La propiedad scroll-margin define la cantidad inicial que se usa para ajustar el cuadro efectivo del objetivo de ajuste de manera similar a la forma en que funciona scroll-padding 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 modifican el cuadro para todas las operaciones de desplazamiento relevantes y no son solo ajustes de 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 RePág y RePág, y también cuando calcula la cantidad 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 del ajuste. Por lo tanto, no es necesario que la secuencia de comandos del usuario realice cálculos manuales para el ajuste.

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 controla cómo se encadena el desplazamiento entre varios elementos y no se ve afectado por el ajuste de desplazamiento.

Advertencias y prácticas recomendadas

Evita usar el ajuste obligatorio 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 de desplazamiento se puede agregar como mejora sin necesidad de detectar funciones. 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. La fijación 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().