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

Aprende a trabajar con cronogramas de desplazamiento y cronogramas de vista para crear animaciones basadas en el desplazamiento de forma 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 basadas 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 ella, por ejemplo, los elementos pueden atenuarse a medida que aparecen.

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

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 de desplazamiento 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 ejecutar animaciones impulsadas por el desplazamiento desde el 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, configura un animation-duration para determinar cuánto tiempo debe durar la animación. Hay más propiedades de escritura manual animation-* disponibles, como animation-easing-function y animation-fill-mode, por nombrar solo algunas, que se pueden combinar en la escritura abreviada animation.

Por ejemplo, esta es una animación que aumenta el tamaño de 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() Element 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. Su hora de origen comienza en 0 cuando se carga la página y comienza a avanzar a medida que avanza el tiempo. 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

Consiste en un cronograma de animación vinculado al progreso en la posición de desplazamiento de un contenedor de desplazamiento, conocido como puerto o barra de desplazamiento, a lo largo de un eje determinado. Convierte la posición 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 por tu cuenta

A menudo, un cronograma del progreso del desplazamiento se abrevia como "Cronograma del 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 por tu cuenta

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 forma, se crea un cronograma de desplazamiento anónimo que puedes configurar como el valor de 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 (configuración predeterminada).
  • 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 llegas 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 por tu cuenta

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 se orienta de manera eficaz al control deslizante raíz, ya que es el control deslizante más cercano del elemento #progress, mientras se realiza un seguimiento de su dirección de bloqueo.

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 proceso un poco más detallado, pero puede ser útil cuando no te orientas a una barra de desplazamiento superior o a la barra de desplazamiento raíz, o cuando la página utiliza múltiples 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 en un identificador de tu preferencia. El valor debe comenzar con --.

Para ajustar el eje de 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 incluye un indicador de paso 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 (lo que se determina cuando el control deslizante se desplaza 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 por tu cuenta

El marcado base 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 distribuye los elementos .gallery__entry contenidos de forma 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 hace referencia al cronograma del progreso del desplazamiento --gallery__scrollcontainer con nombre.

@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 un paquete de propiedades con los source y axis de los que deseas 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ásalo como la propiedad timeline y omite cualquier duration si hay alguno.

$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: el timeline creado hace un seguimiento del control deslizante raíz y ajusta el #progress en el eje x del 0% al 100% a medida que te desplazas por la página.

✨ Pruébala por tu cuenta

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. 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 aparecerá gradualmente a medida que cruce el viewport mientras te desplazas.

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

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

Intermezzo: Consulta los intervalos de cronogramas de visualización

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 View especificando 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.

Estos son los intervalos posibles de cronogramas de visualización para los que puedes segmentar tus anuncios:

  • 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 va de 0% a 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 del cronograma de visualización, disponible en https://goo.gle/view-timeline-range-tool

Mirar una grabación

Como puedes observar mientras juegas con estas herramientas de rangos de cronograma de View, algunos rangos pueden segmentarse 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 range-start y range-end se orientan al mismo range-name y abarcan todo el rango (del 0% al 100%), puedes acortar el valor al solo nombre del rango. Por ejemplo, animation-range: entry 0% entry 100%; se puede volver a escribir como 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 imágenes

✨ Pruébala por tu cuenta

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 visualización con nombre en CSS

Del mismo modo que los cronogramas de desplazamiento tienen versiones con nombre, también puedes crear cronogramas de vista 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 aplica el mismo tipo de valores y las mismas reglas para buscar un cronograma con nombre.

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

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 el valor de la propiedad animation-timeline. El resultado visual es exactamente el mismo que antes.

✨ Pruébala por tu cuenta

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

Para crear un cronograma de vistas en JavaScript, crea una instancia nueva 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 al que se le hará 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 por tu cuenta

Más opciones para probar

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

Veamos esta demostración de la lista de contactos en la que 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 por tu cuenta

En esta demostración, cada elemento se decora con un cronograma de View que realiza un seguimiento del elemento a medida que cruza su desplazamiento, pero se le adjuntan dos animaciones impulsadas por el 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 adjuntas a dos intervalos diferentes, 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 por tu cuenta

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

El mecanismo de búsqueda de cronogramas de desplazamiento y de vista con nombre se limita solo a los ancestros de desplazamiento. Sin embargo, con frecuencia, 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 al cronograma con ese nombre un alcance más amplio. 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 para la propiedad animation-timeline.
  • El elemento .scroller, en realidad, 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. Sube por su árbol de ancestros y encuentra --tl en .parent. Con el --tl en el .parent que apunta al --tl de .scroller, .subject hará un seguimiento, en esencia, 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 vista.

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 el desplazamiento.

Una de las demostraciones adicionales es esta lista de portadas de álbumes. Cada portada gira en 3D mientras ocupa el centro de atención.

Demostración: Flujo de portada

✨ Pruébala por tu cuenta

O esta demostración de tarjetas apiladas que aprovecha 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 por tu cuenta

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.