Cómo animar elementos durante el desplazamiento con animaciones basadas en desplazamientos

Obtén información sobre cómo trabajar con cronogramas de desplazamiento y visualización de cronogramas para crear animaciones basadas en desplazamientos de manera declarativa.

Animaciones basadas en el desplazamiento

Navegadores compatibles

  • Chrome: 115.
  • Edge: 115.
  • Firefox: Detrás de una marca.
  • Safari: No se admite.

Origen

Las animaciones impulsadas por el desplazamiento son un patrón de UX común en la Web. Una animación basada en desplazamientos está vinculada a la posición de desplazamiento de un contenedor de desplazamiento. Esto significa que, a medida que te desplazas hacia arriba o hacia abajo, la animación vinculada se arrastra hacia delante o hacia atrás en respuesta directa. Algunos ejemplos de esto son los efectos como las imágenes de fondo con paralaje o los indicadores de lectura que se mueven a medida que te desplazas.

Un indicador de lectura sobre un documento, controlado por el desplazamiento.

Un tipo similar de animación impulsada por el desplazamiento es una animación vinculada a la posición de un elemento dentro de su contenedor de desplazamiento. Con él, por ejemplo, los elementos pueden aparecer gradualmente a medida que se visualizan.

Las imágenes de esta página aparecen gradualmente a medida que se visualizan.

La forma clásica de lograr este tipo de efectos es responder a los eventos de desplazamiento en el subproceso principal, lo que genera dos problemas principales:

  • Los navegadores modernos realizan el desplazamiento en un proceso independiente y, por lo tanto, entregan eventos de desplazamiento de forma asíncrona.
  • Las animaciones del subproceso principal están sujetas a bloqueos.

Esto hace que sea imposible o muy difícil crear animaciones basadas en desplazamientos de alto rendimiento que estén sincronizadas con el desplazamiento.

A partir de la versión 115 de Chrome, hay un nuevo conjunto de APIs y conceptos que puedes usar para habilitar animaciones declarativas basadas en el desplazamiento: líneas de tiempo de desplazamiento y líneas de tiempo de vista.

Estos conceptos nuevos se integran en la API de Web Animations (WAAPI) y la API de CSS Animations existentes, lo que les permite heredar las ventajas que ofrecen estas APIs. Esto incluye la capacidad de hacer que las animaciones basadas en desplazamientos se ejecuten fuera del subproceso principal. Sí, leíste bien: ahora puedes tener animaciones suaves y fluidas, impulsadas por el desplazamiento, que se ejecutan en el subproceso principal con solo unas pocas líneas de código adicional. ¿Qué no te gusta?

Animaciones en la Web: un pequeño resumen

Animaciones en la Web con CSS

Para crear una animación en CSS, define un conjunto de fotogramas clave con la regla de anidación @keyframes. Vincúlala a un elemento con la propiedad animation-name y, además, establece un animation-duration para determinar cuánto tiempo debe durar la animación. Hay más propiedades de larga duración de animation-* disponibles, animation-easing-function y animation-fill-mode, por nombrar algunas, que se pueden combinar en la abreviatura animation.

Por ejemplo, esta es una animación que escala verticalmente un elemento en el eje X y, al mismo tiempo, cambia su color de fondo:

@keyframes scale-up {
  from {
    background-color: red;
    transform: scaleX(0);
  }
  to {
    background-color: darkred;
    transform: scaleX(1);
  }
}

#progressbar {
  animation: 2.5s linear forwards scale-up;
}
.

Animaciones en la Web con JavaScript

En JavaScript, se puede usar la API de Web Animations para lograr exactamente lo mismo. Para ello, crea instancias nuevas de Animation y KeyFrameEffect, o usa el método animate() de Element, que es mucho más corto.

document.querySelector('#progressbar').animate(
  {
    backgroundColor: ['red', 'darkred'],
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    duration: 2500,
    fill: 'forwards',
    easing: 'linear',
   }
);

Este resultado visual del fragmento de JavaScript anterior es idéntico a la versión anterior de CSS.

Cronogramas de animación

De forma predeterminada, una animación adjunta a un elemento se ejecuta en el cronograma del documento. La hora de origen comienza en 0 cuando se carga la página y comienza a avanzar a medida que avanza la hora del reloj. En eso consiste el cronograma predeterminado para animaciones y, hasta el día de hoy, era el único al que se podía acceder.

La Especificación de animaciones basadas en desplazamientos define dos tipos nuevos de cronogramas que puedes usar:

  • Cronograma del progreso del desplazamiento: Es un cronograma vinculado a la posición de desplazamiento de un contenedor de desplazamiento a lo largo de un eje determinado.
  • Cronograma del progreso de visualización: Es un cronograma vinculado a la posición relativa de un elemento en particular dentro de su contenedor de desplazamiento.

Cronograma del progreso del desplazamiento

El cronograma del progreso del desplazamiento es un cronograma de animación vinculado al progreso en la posición de desplazamiento de un contenedor de desplazamiento, también llamado scrollport o scroller, a lo largo de un eje en particular. Convierte una posición dentro de un intervalo de desplazamiento en un porcentaje de progreso.

La posición inicial de desplazamiento representa un progreso del 0% y la posición final representa un progreso del 100%. En la siguiente visualización, puedes ver que el progreso aumenta del 0% al 100% a medida que te desplazas por la barra de desplazamiento de arriba abajo.

Visualización de un cronograma de progreso del desplazamiento. A medida que te desplazas hacia la parte inferior del control deslizante, el valor de progreso aumenta del 0% al 100%.

✨ Pruébala tú mismo

El cronograma del progreso del desplazamiento a menudo se abrevia como "Cronograma de desplazamiento".

Cronograma del progreso de la visualización

Este tipo de cronograma se vincula al progreso relativo de un elemento particular dentro de un contenedor de desplazamiento. Al igual que en un cronograma del progreso del desplazamiento, se realiza el seguimiento del desplazamiento de una barra de desplazamiento. Pero, difieren en que es la posición relativa de un objeto dentro de ese cronograma lo que determina el progreso.

Esto es comparable al funcionamiento de IntersectionObserver, que puede hacer un seguimiento de la visibilidad de un elemento en la barra de desplazamiento. Si el elemento no se visualiza en la barra de desplazamiento, no hay una intersección. Si es visible en la barra de desplazamiento, incluso para la parte más pequeña, hay una intersección.

Un cronograma del progreso de visualización comienza desde el momento en el que un objeto comienza a cruzarse con la barra de desplazamiento y termina cuando deja de hacerlo. En la siguiente visualización, puedes ver que el progreso comienza en 0% cuando el objeto ingresa al contenedor de desplazamiento y llega al 100% en el momento en que sale de él.

Visualización de un cronograma de progreso de la vista. El progreso aumenta del 0% al 100% a medida que el sujeto (cuadro verde) cruza el control deslizante.

✨ Pruébala tú mismo

A menudo, un cronograma del progreso de visualización se abrevia simplemente como "Cronograma de visualización". Es posible segmentar partes específicas de un cronograma de visualización según el tamaño del sujeto, pero hablaremos de esto más adelante.

Cómo usar los cronogramas del progreso del desplazamiento

Cómo crear un cronograma anónimo del progreso del desplazamiento en CSS

La forma más sencilla de crear un cronograma de desplazamiento en CSS es usar la función scroll(). De esta manera, se crea un cronograma de desplazamiento anónimo que puedes establecer como valor para la nueva propiedad animation-timeline.

Ejemplo:

@keyframes animate-it {  }

.subject {
  animation: animate-it linear;
  animation-timeline: scroll(root block);
}

La función scroll() acepta los argumentos <scroller> y <axis>.

Los valores aceptados para el argumento <scroller> son los siguientes:

  • nearest: Utiliza el contenedor de desplazamiento principal más cercano (predeterminado).
  • root: Utiliza el viewport del documento como el contenedor de desplazamiento.
  • self: Utiliza el elemento como contenedor de desplazamiento.

Los valores aceptados para el argumento <axis> son los siguientes:

  • block: Utiliza la medida de progreso junto con el eje de bloque del contenedor de desplazamiento (configuración predeterminada).
  • inline: Utiliza la medición del progreso junto con el eje intercalado del contenedor de desplazamiento.
  • y: Utiliza la medida de progreso junto con el eje y del contenedor de desplazamiento.
  • x: Utiliza la medida de progreso junto con el eje x del contenedor de desplazamiento.

Por ejemplo, para vincular una animación al desplazador raíz en el eje de bloque, los valores que se deben pasar a scroll() son root y block. En conjunto, el valor es scroll(root block).

Demostración: Indicador de progreso de lectura

Esta demostración tiene un indicador de progreso de lectura fijo en la parte superior del viewport. A medida que te desplazas hacia abajo en la página, la barra de progreso crece hasta ocupar el ancho completo del viewport cuando llega al final del documento. Se usa un cronograma anónimo del progreso del desplazamiento para controlar la animación.

Demostración: Indicador de progreso de lectura.

✨ Pruébala

El indicador de progreso de lectura se coloca en la parte superior de la página con la posición fija. Para aprovechar las animaciones compuestas, no se anima el width, sino que el elemento se reduce en el eje x con un transform.

<body>
  <div id="progress"></div>
  …
</body>
@keyframes grow-progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

#progress {
  position: fixed;
  left: 0; top: 0;
  width: 100%; height: 1em;
  background: red;

  transform-origin: 0 50%;
  animation: grow-progress auto linear;
  animation-timeline: scroll();
}

El cronograma de la animación grow-progress en el elemento #progress se establece en un cronograma anónimo que se crea con scroll(). No se proporcionan argumentos a scroll(), por lo que se recurrirá a sus valores predeterminados.

El control deslizante predeterminado para hacer un seguimiento es el de nearest, y el eje predeterminado es block. Esto apunta eficazmente a la barra de desplazamiento raíz, ya que es la barra de desplazamiento más cercana al elemento #progress, al tiempo que hace un seguimiento de la dirección de su bloque.

Cómo crear un cronograma del progreso del desplazamiento con nombre en CSS

Una forma alternativa para definir el cronograma del progreso de desplazamiento es usar uno que tenga nombre. Es un poco más detallada, pero puede ser útil cuando no te orientas a una barra de desplazamiento superior o a la barra de desplazamiento raíz, cuando la página utiliza varios cronogramas o cuando las búsquedas automáticas no funcionan. De esta forma, puedes identificar un cronograma del progreso del desplazamiento por el nombre que le asignaste.

Para crear un cronograma del progreso del desplazamiento con nombre en un elemento, configura la propiedad CSS de scroll-timeline-name en el contenedor de desplazamiento con un identificador de tu gusto. El valor debe comenzar con --.

Para modificar el eje para el que se realizará el seguimiento, también declara la propiedad scroll-timeline-axis. Los valores permitidos son los mismos del argumento <axis> de scroll().

Finalmente, para vincular la animación al cronograma del progreso del desplazamiento, define la propiedad animation-timeline en el elemento que se debe animar con el mismo valor que el identificador que se usó para scroll-timeline-name.

Ejemplo de código:

@keyframes animate-it {  }

.scroller {
  scroll-timeline-name: --my-scroller;
  scroll-timeline-axis: inline;
}

.scroller .subject {
  animation: animate-it linear;
  animation-timeline: --my-scroller;
}

Si lo deseas, puedes combinar scroll-timeline-name y scroll-timeline-axis en la abreviatura scroll-timeline. Por ejemplo:

scroll-timeline: --my-scroller inline;

Esta demostración presenta un indicador de pasos que se muestra sobre cada carrusel de imágenes. Cuando un carrusel contiene tres imágenes, la barra del indicador comienza con un ancho del 33% para indicar que estás viendo la primera de las tres imágenes. Cuando la última imagen está en la vista (determinada por el hecho de que el control deslizante se haya desplazado hasta el final), el indicador ocupa todo el ancho del control deslizante. Se usa un cronograma del progreso del desplazamiento con nombre para controlar la animación.

Demostración: Indicador de paso de carrusel horizontal.

✨ Pruébala tú mismo

El lenguaje de marcado básico de una galería es el siguiente:

<div class="gallery" style="--num-images: 2;">
  <div class="gallery__scrollcontainer">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">…</div>
    <div class="gallery__entry">…</div>
  </div>
</div>

El elemento .gallery__progress se posiciona de forma absoluta dentro del elemento de wrapper .gallery. Su tamaño inicial está determinado por la propiedad personalizada --num-images.

.gallery {
  position: relative;
}


.gallery__progress {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 1em;
  transform: scaleX(calc(1 / var(--num-images)));
}

El .gallery__scrollcontainer establece los elementos .gallery__entry contenidos de manera horizontal y es el elemento que se desplaza. Cuando se realiza un seguimiento de su posición de desplazamiento, el .gallery__progress se anima. Para ello, se debe hacer referencia al cronograma del progreso del desplazamiento --gallery__scrollcontainer denominado.

@keyframes grow-progress {
  to { transform: scaleX(1); }
}

.gallery__scrollcontainer {
  overflow-x: scroll;
  scroll-timeline: --gallery__scrollcontainer inline;
}
.gallery__progress {
  animation: auto grow-progress linear forwards;
  animation-timeline: --gallery__scrollcontainer;
}

Cómo crear un cronograma del progreso del desplazamiento con JavaScript

Para crear un cronograma de desplazamiento en JavaScript, crea una instancia nueva de la clase ScrollTimeline. Pasa una bolsa de propiedad con el source y el axis de los que quieres hacer un seguimiento.

  • source: Es una referencia al elemento cuyo control deslizante deseas seguir. Usa document.documentElement para segmentar el control deslizante raíz.
  • axis: Determina a qué eje se le debe hacer un seguimiento. Al igual que en la variante de CSS, los valores aceptados son block, inline, x y y.
const tl = new ScrollTimeline({
  source: document.documentElement,
});

Para adjuntarlo a una animación web, pásala como la propiedad timeline y omite cualquier duration si hubiera.

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
});

Demostración: Indicador de progreso de lectura, revisión

Para volver a crear el indicador de progreso de lectura con JavaScript, mientras usas el mismo marcado, usa el siguiente código de JavaScript:

const $progressbar = document.querySelector('#progress');

$progressbar.style.transformOrigin = '0% 50%';
$progressbar.animate(
  {
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    fill: 'forwards',
    timeline: new ScrollTimeline({
      source: document.documentElement,
    }),
  }
);

El resultado visual es idéntico en la versión de CSS: la timeline creada hace un seguimiento del desplazamiento raíz y aumenta la escala de #progress en el eje x del 0% al 100% a medida que te desplazas por la página.

✨ Pruébala tú mismo

Cómo usar el cronograma del progreso de visualización

Cómo crear un cronograma anónimo del progreso de visualización en CSS

Para crear un cronograma del progreso de visualización, usa la función view(). Los argumentos que acepta son <axis> y <view-timeline-inset>.

  • El valor <axis> es el mismo que se utiliza para el cronograma del progreso de desplazamiento y define los ejes a los que se les hace seguimiento. El valor predeterminado es block.
  • Con <view-timeline-inset>, puedes especificar un desplazamiento (positivo o negativo) para ajustar los límites cuando se considera que un elemento está en la vista o no. El valor debe ser un porcentaje o auto, siendo auto el valor predeterminado.

Por ejemplo, para vincular una animación a un elemento que se cruza con su desplazador en el eje de bloque, usa view(block). De manera similar a scroll(), establece esto como el valor de la propiedad animation-timeline y no olvides establecer animation-duration en auto.

Con el siguiente código, cada img tendrá un fundido de entrada a medida que cruce el viewport durante el desplazamiento.

@keyframes reveal {
  from { opacity: 0; }
  to { opacity: 1; }
}

img {
  animation: reveal linear;
  animation-timeline: view();
}

Intermezzo: Cómo ver intervalos de Rutas

De forma predeterminada, una animación vinculada al cronograma de la vista se adjunta a todo su intervalo. Esta comienza desde el momento en que el objeto está a punto de ingresar al puerto de desplazamiento y finaliza cuando sale de él por completo.

También es posible vincularla a una parte específica del cronograma de visualización indicando el intervalo al que se debe adjuntar. Por ejemplo, solo cuando el objeto ingresa en la barra de desplazamiento. En la siguiente visualización, el progreso comienza en 0% cuando el objeto ingresa al contenedor de desplazamiento, pero ya alcanza el 100% desde el momento en que se conecta por completo.

Un cronograma de View configurado para hacer un seguimiento del intervalo de entrada del sujeto. La animación solo se ejecuta mientras el objeto ingresa al puerto de desplazamiento.

Los posibles intervalos de cronogramas de visualización a los que te puedes orientar son los siguientes:

  • cover: Representa el intervalo completo del cronograma del progreso de visualización.
  • entry: Representa el intervalo durante el cual el cuadro principal ingresa al intervalo de visibilidad del progreso de visualización.
  • exit: Representa el intervalo durante el cual el cuadro principal sale del intervalo de visibilidad del progreso de visualización.
  • entry-crossing: Representa el intervalo durante el cual el cuadro principal cruza el límite del borde final.
  • exit-crossing: Representa el intervalo durante el cual el cuadro principal cruza el límite del borde inicial.
  • contain: Representa el intervalo durante el cual el cuadro principal está completamente contenido en su intervalo de visibilidad del progreso de visualización dentro del puerto de desplazamiento, o lo cubre por completo. Esto depende de si el objeto es más alto o bajo que la barra de desplazamiento.

Para definir un rango, debes establecer un rango de inicio y un rango de finalización. Cada uno consta de un nombre de rango (consulta la lista anterior) y un desplazamiento de rango para determinar la posición dentro de ese nombre de rango. Por lo general, el desplazamiento de rango es un porcentaje que oscila entre 0% y 100%, pero también puedes especificar una longitud fija, como 20em.

Por ejemplo, si deseas ejecutar una animación desde el momento en que entra un sujeto, elige entry 0% como el inicio del rango. Para que finalice cuando ingrese el sujeto, elige entry 100% como valor para el final del rango.

En CSS, puedes configurar esto con la propiedad animation-range. Ejemplo:

animation-range: entry 0% entry 100%;

En JavaScript, usa las propiedades rangeStart y rangeEnd.

$el.animate(
  keyframes,
  {
    timeline: tl,
    rangeStart: 'entry 0%',
    rangeEnd: 'entry 100%',
  }
);

Usa la herramienta incorporada a continuación para ver lo que representa cada nombre de intervalo y cómo afectan los porcentajes a las posiciones iniciales y finales. Intenta establecer range-start en entry 0% y range-end en cover 50% y, luego, arrastra la barra de desplazamiento para ver el resultado de la animación.

El visualizador de intervalos de cronograma de visualización, disponible en https://goo.gle/view-timeline-range-tool

Mirar una grabación

Como puedes notar al explorar las herramientas de visualización de intervalos de cronograma, algunos rangos se pueden seleccionar con dos combinaciones diferentes de nombre de rango y desplazamiento de rango. Por ejemplo, entry 0%, entry-crossing 0% y cover 0% se orientan a la misma área.

Cuando el rango de inicio y finalización del rango tienen como objetivo el mismo nombre de rango y abarcan todo el rango (de 0% a 100%), puedes acortar el valor para simplemente el nombre del rango. Por ejemplo, animation-range: entry 0% entry 100%; se puede reescribir a animation-range: entry, que es mucho más corto.

Demostración: Revelación de imágenes

En esta demostración, las imágenes se atenúan a medida que entran en el puerto de desplazamiento. Esto se hace con un cronograma de vistas anónimas. Se modificó el rango de animación para que cada imagen tenga opacidad completa cuando esté a la mitad del control deslizante.

Demostración: Revelación de imagen

✨ Pruébala tú mismo

El efecto de expansión se logra con un clip-path animado. El CSS que se usa para este efecto es el siguiente:

@keyframes reveal {
  from { opacity: 0; clip-path: inset(0% 60% 0% 50%); }
  to { opacity: 1; clip-path: inset(0% 0% 0% 0%); }
}

.revealing-image {
  animation: auto linear reveal both;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

Cómo crear un cronograma del progreso de la visualización con nombre en CSS

Así como los cronogramas de desplazamiento tienen versiones con nombre, también puedes crear cronogramas de visualización con nombre. En lugar de las propiedades scroll-timeline-*, usas variantes que llevan el prefijo view-timeline-, es decir, view-timeline-name y view-timeline-axis.

Se aplican el mismo tipo de valores y las mismas reglas para buscar un cronograma con nombre.

Demostración: Revelación de imágenes, revisión

Si vuelves a trabajar en la demostración de revelación de imágenes anterior, el código revisado se verá de la siguiente manera:

.revealing-image {
  view-timeline-name: --revealing-image;
  view-timeline-axis: block;

  animation: auto linear reveal both;
  animation-timeline: --revealing-image;
  animation-range: entry 25% cover 50%;
}

Con view-timeline-name: revealing-image, se realizará un seguimiento del elemento dentro de su control de desplazamiento más cercano. Luego, se usa el mismo valor como valor de la propiedad animation-timeline. El resultado visual es exactamente el mismo que antes.

✨ Pruébala tú mismo

Cómo crear un cronograma del progreso de visualización en JavaScript

Para crear un cronograma de visualización en JavaScript, crea una nueva instancia de la clase ViewTimeline. Pasa un paquete de propiedades con el subject del que deseas hacer un seguimiento, axis y inset.

  • subject: Es una referencia al elemento del que deseas hacer un seguimiento dentro de su propio control de desplazamiento.
  • axis: Es el eje para realizar un seguimiento. Al igual que en la variante de CSS, los valores aceptados son block, inline, x y y.
  • inset: Es un ajuste de desplazamiento (positivo) o de desplazamiento hacia afuera (negativo) del puerto de desplazamiento cuando se determina si el cuadro está en la vista.
const tl = new ViewTimeline({
  subject: document.getElementById('subject'),
});

Para adjuntarlo a una animación web, pásalo como la propiedad timeline y omite cualquier duration si hay alguno. De manera opcional, pasa la información del rango con las propiedades rangeStart y rangeEnd.

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
  rangeStart: 'entry 25%',
  rangeEnd: 'cover 50%',
});

✨ Pruébala tú mismo

Más opciones para probar

Cómo adjuntar a varios rangos de cronograma de View con un conjunto de fotogramas clave

Echemos un vistazo a esta demostración de lista de contactos donde las entradas de la lista están animadas. Cuando una entrada de lista ingresa al puerto de desplazamiento desde la parte inferior, se desliza y se desvanece, y cuando sale del puerto de desplazamiento en la parte superior, se desliza y se desvanece.

Demostración: Lista de contactos

✨ Pruébala

Para esta demostración, cada elemento se decora con un cronograma de visualización que lo hace a medida que cruza su puerto de desplazamiento, pero se adjuntan dos animaciones basadas en desplazamiento. La animación animate-in se adjunta al rango entry del cronograma, y la animación animate-out al rango exit del cronograma.

@keyframes animate-in {
  0% { opacity: 0; transform: translateY(100%); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes animate-out {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-100%); }
}

#list-view li {
  animation: animate-in linear forwards,
             animate-out linear forwards;
  animation-timeline: view();
  animation-range: entry, exit;
}

En lugar de ejecutar dos animaciones diferentes unidas a dos intervalos distintos, también es posible crear un conjunto de fotogramas clave que ya contenga la información del intervalo.

@keyframes animate-in-and-out {
  entry 0%  {
    opacity: 0; transform: translateY(100%);
  }
  entry 100%  {
    opacity: 1; transform: translateY(0);
  }
  exit 0% {
    opacity: 1; transform: translateY(0);
  }
  exit 100% {
    opacity: 0; transform: translateY(-100%);
  }
}

#list-view li {
  animation: linear animate-in-and-out;
  animation-timeline: view();
}

Como los fotogramas clave contienen la información del intervalo, no es necesario que especifiques el animation-range. El resultado es exactamente el mismo que antes.

✨ Pruébala tú mismo

Cómo adjuntarse a un cronograma de desplazamiento que no es ancestro

El mecanismo de búsqueda para cronogramas de desplazamiento con nombre y cronogramas de visualización se limita a los principales de desplazamiento únicamente. Sin embargo, a menudo, el elemento que se debe animar no es un elemento secundario del control de desplazamiento al que se debe hacer un seguimiento.

Para que esto funcione, entra en juego la propiedad timeline-scope. Usas esta propiedad para declarar un cronograma con ese nombre sin crearlo. Esto le da un alcance más amplio a la línea de tiempo con ese nombre. En la práctica, usas la propiedad timeline-scope en un elemento superior compartido para que la línea de tiempo de un control deslizante secundario pueda adjuntarse a él.

Por ejemplo:

.parent {
  timeline-scope: --tl;
}
.parent .scroller {
  scroll-timeline: --tl;
}
.parent .scroller ~ .subject {
  animation: animate linear;
  animation-timeline: --tl;
}

En este fragmento, ocurre lo siguiente:

  • El elemento .parent declara un cronograma con el nombre --tl. Cualquier elemento secundario puede encontrarlo y usarlo como valor de la propiedad animation-timeline.
  • En realidad, el elemento .scroller define un cronograma de desplazamiento con el nombre --tl. De forma predeterminada, solo sus elementos secundarios podrían verlo, pero como .parent lo configuró como scroll-timeline-root, se adjunta a él.
  • El elemento .subject usa el cronograma --tl. Camina hasta su árbol principal y encuentra --tl en .parent. Con la --tl del .parent apuntando al --tl de .scroller, .subject básicamente hará un seguimiento del cronograma del progreso del desplazamiento de .scroller.

En otras palabras, puedes usar timeline-root para mover un cronograma hasta un ancestro (también conocido como elevación) para que todos los elementos secundarios del ancestro puedan acceder a él.

La propiedad timeline-scope se puede usar con cronogramas de desplazamiento y de visualización.

Más demostraciones y recursos

Todas las demostraciones que se incluyen en este artículo se encuentran en el minisitio scroll-driven-animations.style. El sitio web incluye muchas más demostraciones para destacar lo que es posible hacer con las animaciones impulsadas por desplazamiento.

Una de las demostraciones adicionales es esta lista de portadas de álbumes. Cada portada gira en 3D a medida que toma el foco central.

Demostración: Flujo de portada

✨ Pruébala tú mismo

También puedes ver esta demostración de tarjetas apiladas que aprovechan position: sticky. A medida que se apilan las tarjetas, las que ya están pegadas se reducen, lo que crea un buen efecto de profundidad. Al final, toda la pila desaparece de la vista como un grupo.

Demostración: Tarjetas apiladas.

✨ Pruébala tú mismo

También se incluye en scroll-driven-animations.style una colección de herramientas, como la visualización del progreso del rango de cronograma de View que se incluyó anteriormente en esta publicación.

Las animaciones impulsadas por el desplazamiento también se abordan en Novedades sobre Web Animations en Google I/O 2023.