Cómo crear una animación escalonada

Las animaciones escalonadas proporcionan un efecto interesante en el que varios elementos ordenados se animan de forma secuencial con un ligero retraso entre cada uno, en lugar de animarse todos a la vez. Esta técnica se suele usar en listas, galerías o menús de navegación para guiar la mirada del usuario y agregar una sensación rítmica y refinada a las interacciones.

Escalona animaciones con sibling-index()

Usa la propiedad sibling-index() en la propiedad animation-delay para que la animación de cada elemento se desplace en un número proporcional a su posición en el elemento superior. La función sibling-index() devuelve un número entero, por lo que se debe multiplicar por una unidad de tiempo para convertirlo en un valor de tiempo.

#stagger-list > .item {
  --stagger-time: 0.1s;
  /* Define the animation first */
  animation: fade-in 0.4s;
  /* Set the `animation-delay` to a time multiplied by the `sibling-index()` */
  animation-delay: calc(sibling-index() * var(--stagger-time))
}

OBLIGATORIO: Respeta las preferencias del usuario inhabilitando la animación para los usuarios que prefieren un movimiento reducido.

@media (prefers-reduced-motion: reduce){
  /* Disable animation for users who prefer reduced motion. */
  #stagger-list > .item {
    animation: none;
  }
}

Estrategias de resguardo

Prueba la compatibilidad con sibling-index() usando CSS con @supports (animation-delay: calc(sibling-index() * 0.1s)){} o JavaScript con !CSS.supports('animation-delay: calc(sibling-index() * 0.1s)').

Para admitir animaciones escalonadas en navegadores más antiguos, usa JavaScript para agregar una propiedad personalizada --sibling-index a cada elemento hermano. OBLIGATORIO: Encierra esto en una prueba de CSS.supports('animation-delay: calc(sibling-index() * 0.1s)') para evitar que se ejecute JavaScript innecesario.

if(!CSS.supports('animation-delay: calc(sibling-index() * 0.1s)')){
  const staggerList = document.getElementById('stagger-list');
  [...staggerList.children].forEach((el, index)=>el.style.setProperty('--sibling-index', index + 1));
}

Agrega una declaración animation-delay que use la propiedad personalizada --sibling-index. Debe estar antes de la declaración animation-delay que usa la función sibling-index(). No es necesario que esto se incluya en @supports; los navegadores más antiguos no analizarán la segunda declaración y usarán la primera.

#stagger-list > .item {
  animation-delay: calc(var(--sibling-index) * var(--stagger-time));
  animation-delay: calc(sibling-index() * var(--stagger-time));
}