Desplazamiento bien controlado con Snap de desplazamiento de CSS

Crea experiencias de desplazamiento bien controladas declarando posiciones de ajuste de desplazamiento.

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

La función CSS Scroll Snap 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 uso común de esto. CSS Scroll Snap proporciona una API coherente y fácil de usar para compilar estos patrones populares de UX.

Información general

Caso para el ajuste de desplazamiento

El desplazamiento es una forma popular y natural de interactuar con el contenido de 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, y se vuelve crucial en plataformas 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. Rara vez 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 lo deja parcialmente visible. Estos casos de uso se benefician de una experiencia de desplazamiento bien controlada.

Desde hace mucho tiempo, los desarrolladores web confían en las soluciones basadas en JavaScript para controlar el desplazamiento y 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 de desplazamiento o acceso al desplazamiento compuesto. CSS Scroll Snap garantiza una solución rápida, de alta fidelidad y fácil de usar que funciona de manera coherente en todos los navegadores.

CSS Scroll Snap permite a los autores web marcar cada contenedor de desplazamiento con límites para las operaciones de desplazamiento en las que se finalizan. 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 a esta sin problemas. Volviendo al ejemplo anterior, cuando el usuario termina de desplazarse por el carrusel, su imagen visible se encaja en su lugar. JavaScript no necesita ajustes de desplazamiento.

Ejemplo del uso de un ajuste de desplazamiento de CSS con un carrusel de imágenes
Ejemplo de uso de una toma de desplazamiento de CSS con un carrusel de imágenes. Aquí, el ajuste del desplazamiento garantiza que, al final del desplazamiento, se alinee el centro horizontal de la imagen con el centro horizontal del contenedor de desplazamiento.

Ajustes de desplazamiento de CSS

El ajuste de desplazamiento es la acción 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.

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

Se puede producir una posición de ajuste declarando 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 según lo especificado para el eje dado. Los siguientes alineamientos son posibles en cada eje: start, end, center.

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

Ejemplo de varias alineaciones en el eje de desplazamiento horizontal.

Los siguientes ejemplos ilustran cómo usar estos conceptos.

Un caso de uso común para ajustar el desplazamiento es un carrusel de imágenes. Por ejemplo, para crear un carrusel de imágenes horizontal que se ajusta 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 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>

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 del desplazamiento. Por ejemplo, considera el caso en el que una imagen es más grande que el carrusel. Un algoritmo de ajuste simple puede evitar que el usuario se desplace para ver la imagen completa. Sin embargo, la especificación requiere que las implementaciones detecten este caso y permitan al usuario desplazarse libremente dentro de esa imagen solo para ajustarse en sus bordes.

Ver demostración | Fuente

Ejemplo: una página de producto con 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 una opción más natural para casos como este. No interfiere cuando un usuario se desplaza al centro de una sección en particular, sino que también se ajusta y dirige la atención a una sección nueva cuando se desplaza lo suficiente.

A continuación, te indicamos 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 del desplazamiento

La página del producto tiene un encabezado superior en una posición fija. El diseño también solicitaba que parte de la sección superior permanezca visible cuando se ajusta el contenedor de desplazamiento para proporcionar una señal de diseño a los usuarios sobre el contenido anterior.

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 una inserción en el cuadro de relleno del contenedor de desplazamiento. En nuestro ejemplo, se agregó la inserción adicional 15vh en 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 de desplazamiento. Cuando se aplica el ajuste, el borde inicial del elemento de destino del ajuste se limpiará con esta nueva posición, lo que dejará espacio encima.

La propiedad scroll-margin define el importe de salida que se usa para ajustar el cuadro efectivo del objetivo de ajuste de manera similar al funcionamiento de scroll-padding en el contenedor de desplazamiento de ajuste.

Quizás 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 son solo ajustes de desplazamiento. Por ejemplo, Chrome los tiene en cuenta a la hora de calcular 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().

Ver demostración | Fuente

Interacción con otras APIs de desplazamiento

API de DOM Scrolling

Los ajustes de desplazamiento se producen 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 para la operación y, luego, aplicará la lógica de ajuste adecuada para encontrar la ubicación ajustada final. Por lo tanto, no es necesario que la secuencia de comandos del usuario haga ningún cálculo manual para el ajuste.

Desplazamiento fluido

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

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

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

Detección de atributos 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 des por sentado que las APIs de desplazamiento de manera programática, como Element.scrollTo, siempre finalizan en el desplazamiento solicitado. El ajuste de desplazamiento puede ajustar el desplazamiento una vez 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 el caso, en especial, del ajuste de desplazamiento.

Trabajo futuro

Una encuesta reciente del equipo de Chrome se centró en la experiencia de desplazamiento. En los resultados de la encuesta, se identificaron varias áreas que necesitan trabajo adicional para reducir la brecha entre las bibliotecas de complementos y las CSS. El próximo trabajo se centrará en scroll-snap, incluido lo siguiente:

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