
Las scroll-driven animations son una de las novedades más interesantes de CSS moderno porque permiten crear animaciones vinculadas directamente al desplazamiento del usuario. En lugar de depender únicamente del tiempo, como ocurre con una animación tradicional, este tipo de animación avanza según el scroll de la página o según la posición de un elemento dentro del viewport.
Dicho de otra forma: ya no necesitamos pensar siempre en animaciones que duran “un segundo” o “medio segundo”. Ahora podemos crear efectos que progresan a medida que la persona navega por el contenido. Esto abre la puerta a barras de progreso de lectura, tarjetas que aparecen al entrar en pantalla, imágenes que se transforman durante el recorrido o secciones narrativas que acompañan visualmente al usuario.
Si ya has trabajado con animaciones CSS, probablemente estés familiarizada con @keyframes, animation, transition, opacity o transform. Las scroll-driven animations parten de esa misma base, pero introducen una diferencia importante: la línea de tiempo de la animación deja de estar controlada por segundos y pasa a estar controlada por el scroll.
En este artículo vamos a ver qué son las animaciones con scroll CSS, cómo funcionan, qué papel tienen animation-timeline, scroll() y view(), cuándo conviene usarlas y qué buenas prácticas deberías aplicar para que el resultado sea fluido, accesible y útil.
Qué son las scroll-driven animations en CSS
Las scroll-driven animations son animaciones cuyo progreso depende del desplazamiento del usuario. En una animación CSS tradicional, el navegador reproduce una secuencia durante un tiempo concreto. Por ejemplo, puedes hacer que una tarjeta pase de opacity: 0 a opacity: 1 durante 0.4s.
.card {
opacity: 0;
transform: translateY(24px);
animation: aparecer 0.4s ease forwards;
}
@keyframes aparecer {
to {
opacity: 1;
transform: translateY(0);
}
}
En este caso, la animación empieza, dura un tiempo determinado y termina. El usuario no controla su progreso. Puede activarse al cargar la página, al añadir una clase o al interactuar con un elemento, pero la animación en sí avanza por tiempo.
Con una scroll animation CSS, la lógica cambia. El progreso de la animación se vincula al scroll. Si el usuario baja por la página, la animación avanza. Si se detiene, la animación se detiene. Si vuelve hacia arriba, la animación puede retroceder.
Esta relación directa entre movimiento y desplazamiento permite crear experiencias más conectadas con el ritmo real de navegación.
La diferencia clave está en la línea de tiempo
Toda animación necesita una línea de tiempo. En CSS clásico, esa línea de tiempo suele estar basada en segundos. Con las scroll-driven animations, esa línea de tiempo puede depender del desplazamiento de la página o de la visibilidad de un elemento.
Por eso, cuando hablamos de CSS scroll timeline, hablamos de una forma distinta de calcular el progreso de una animación. Ya no preguntamos “cuánto tiempo ha pasado”, sino “cuánto ha avanzado el usuario en el scroll” o “qué parte del elemento está visible”.
Esto es especialmente útil en páginas largas, artículos técnicos, landings, portfolios, documentación o experiencias de storytelling visual.
Conceptos básicos: animation-timeline, scroll() y view()
Para usar scroll-driven animations en CSS, hay tres conceptos que conviene tener claros: animation-timeline, scroll() y view().
animation-timeline
La propiedad animation-timeline permite indicar qué línea de tiempo controla una animación. Por defecto, una animación CSS usa una línea de tiempo basada en el tiempo del documento. Pero con esta propiedad podemos asociarla a una línea de tiempo basada en scroll.
.elemento {
animation: revelar linear both;
animation-timeline: scroll();
}
En este ejemplo, la animación revelar no avanza por duración temporal, sino por el progreso del scroll.
Un detalle importante: si usas la propiedad abreviada animation, conviene declarar animation-timeline después. Así evitas que el shorthand sobrescriba valores relacionados con la animación.
.elemento {
animation: revelar linear both;
animation-timeline: view();
}
Si quieres profundizar en cómo funcionan las animaciones tradicionales antes de pasar a este nivel, puede ayudarte repasar la diferencia entre transition y animation en CSS, porque entender esa base facilita mucho el uso de timelines más avanzadas.
scroll(): animar según el progreso del scroll
La función scroll() vincula la animación al desplazamiento de un contenedor. Puede ser el scroll principal de la página o el de un contenedor concreto.
Uno de los ejemplos más claros es una barra de progreso de lectura.
<div class="reading-progress"></div>
.reading-progress {
position: fixed;
top: 0;
left: 0;
z-index: 1000;
width: 100%;
height: 4px;
transform: scaleX(0);
transform-origin: left;
background: currentColor;
animation: grow-progress linear both;
animation-timeline: scroll(root block);
}
@keyframes grow-progress {
to {
transform: scaleX(1);
}
}
Este patrón es muy útil en artículos extensos porque permite mostrar visualmente cuánto contenido se ha recorrido. Además, no requiere JavaScript para calcular el porcentaje de scroll.
El valor scroll(root block) indica que la animación se basa en el scroll principal del documento, en el eje de bloque, que normalmente coincide con el desplazamiento vertical.
view(): animar según la visibilidad del elemento
La función view() sirve para crear animaciones basadas en la entrada y salida de un elemento dentro del viewport o de un contenedor de scroll.
Por ejemplo, podemos hacer que una tarjeta aparezca suavemente al entrar en pantalla:
.card {
opacity: 0;
transform: translateY(32px);
animation: reveal-card linear both;
animation-timeline: view();
animation-range: entry 0% cover 35%;
}
@keyframes reveal-card {
to {
opacity: 1;
transform: translateY(0);
}
}
Aquí, cada tarjeta se anima según su propia relación con el área visible. La animación empieza cuando el elemento entra en pantalla y termina cuando cubre una parte determinada del viewport.
La propiedad animation-range permite ajustar ese tramo. Esto es importante porque no siempre queremos que una animación empiece en el primer píxel visible del elemento. A veces resulta más natural que empiece un poco después y termine antes de que el elemento esté completamente centrado.
Diferencia entre animaciones activadas por scroll y animaciones controladas por scroll
Es habitual confundir las animaciones activadas por scroll con las animaciones controladas por scroll, pero no son exactamente lo mismo.
Una animación activada por scroll suele funcionar así: el usuario llega a una sección, JavaScript detecta que el elemento entra en pantalla y se añade una clase. A partir de ahí, la animación se reproduce durante un tiempo concreto.
.card {
opacity: 0;
transform: translateY(24px);
transition: opacity 0.4s ease, transform 0.4s ease;
}
.card.visible {
opacity: 1;
transform: translateY(0);
}
En este caso, el scroll activa la animación, pero no controla su progreso. Una vez activada, la transición depende del tiempo.
En cambio, en una scroll-driven animation, el scroll no solo dispara el efecto: lo dirige. La animación avanza, se pausa o retrocede según el desplazamiento del usuario.
Esta diferencia es importante porque hace que la experiencia se sienta más fluida y más conectada con la navegación.
Ejemplo práctico: barra de progreso de lectura
Una barra de progreso es uno de los mejores ejemplos para empezar porque tiene una función clara. No es una animación decorativa, sino una ayuda visual para saber cuánto queda de lectura.
<div class="reading-progress"></div>
<article class="post">
<h1>Scroll-driven animations: qué son y cómo usarlas</h1>
<p>Contenido del artículo...</p>
</article>
.reading-progress {
position: fixed;
top: 0;
left: 0;
z-index: 1000;
width: 100%;
height: 4px;
transform: scaleX(0);
transform-origin: left;
animation: reading-progress linear both;
animation-timeline: scroll(root block);
}
@keyframes reading-progress {
to {
transform: scaleX(1);
}
}
Este ejemplo funciona bien porque utiliza transform: scaleX(), una propiedad adecuada para animaciones fluidas. En general, siempre que puedas, es preferible animar transform y opacity antes que propiedades que afecten al layout. Si quieres ampliar esta idea, puedes leer el artículo sobre por qué animar transform y opacity antes que width o height.
Ejemplo práctico: revelar tarjetas al entrar en pantalla
Otro uso muy común de las animaciones con scroll CSS es revelar tarjetas, imágenes o bloques de contenido a medida que aparecen en pantalla.
<section class="grid">
<article class="card">
<h2>Proyecto destacado</h2>
<p>Descripción breve del proyecto.</p>
</article>
<article class="card">
<h2>Otro proyecto</h2>
<p>Descripción breve del proyecto.</p>
</article>
</section>
.card {
opacity: 0;
transform: translateY(32px);
animation: reveal-card linear both;
animation-timeline: view();
animation-range: entry 0% cover 35%;
}
@keyframes reveal-card {
to {
opacity: 1;
transform: translateY(0);
}
}
Este patrón puede funcionar muy bien en portfolios, páginas de servicios, casos de estudio o landings. La clave está en que el efecto sea suave y no interrumpa la lectura.
Si cada elemento aparece con un desplazamiento exagerado, el resultado puede parecer artificial. En cambio, un movimiento breve y sutil puede ayudar a guiar la mirada sin robar protagonismo al contenido.
Cómo ajustar animation-range
La propiedad animation-range permite definir en qué tramo de la línea de tiempo se ejecuta la animación.
animation-range: entry 10% cover 40%;
Este ajuste hace que la animación empiece cuando el elemento ya ha entrado ligeramente en pantalla y termine cuando cubre una parte concreta del viewport.
No existe un único valor correcto. Depende del diseño, del tamaño del elemento, del ritmo de la página y del tipo de experiencia que quieras crear. Por eso conviene probar varios rangos hasta que el movimiento se sienta natural.
Ejemplo práctico: imagen con efecto de escala durante el scroll
Las scroll-driven animations también pueden utilizarse en composiciones más visuales. Por ejemplo, una imagen que aumenta ligeramente de tamaño mientras el usuario recorre una sección.
<section class="hero-scroll">
<img src="imagen.jpg" alt="Detalle visual del proyecto" class="hero-image">
</section>
.hero-scroll {
min-height: 150vh;
}
.hero-image {
position: sticky;
top: 20vh;
width: 100%;
transform: scale(0.9);
animation: zoom-image linear both;
animation-timeline: view();
animation-range: entry 0% exit 100%;
}
@keyframes zoom-image {
to {
transform: scale(1.05);
}
}
Este tipo de efecto puede aportar profundidad en una página editorial o en una sección visual de portfolio. Sin embargo, conviene usarlo con moderación. Un pequeño cambio de escala puede ser elegante; un zoom excesivo puede resultar molesto.
Buenas prácticas para usar scroll-driven animations
Las scroll-driven animations son potentes, pero no deberían aplicarse sin criterio. Como ocurre con cualquier recurso visual, la pregunta principal no es “¿puedo animarlo?”, sino “¿esta animación mejora la experiencia?”.
Usa la animación con una intención clara
Una animación debería aportar orientación, continuidad, feedback o jerarquía visual. Una barra de progreso comunica avance. Una tarjeta que aparece suavemente puede dirigir la atención hacia un bloque importante. Un efecto de escala puede reforzar una narrativa visual.
Pero si la animación no ayuda al usuario a entender mejor la interfaz, quizá sea prescindible. En diseño web, menos movimiento suele ser mejor que demasiado movimiento.
Para decidir cuándo tiene sentido animar y cuándo es mejor evitarlo, te puede interesar revisar esta guía sobre cuándo usar animaciones CSS y cuándo evitarlas.
Prioriza propiedades eficientes
Siempre que sea posible, anima transform y opacity. Estas propiedades suelen ofrecer mejor rendimiento porque no obligan al navegador a recalcular la estructura completa de la página en cada paso de la animación.
Por ejemplo, para una barra de progreso, es mejor utilizar transform: scaleX() que modificar directamente el ancho con width.
/* Mejor opción */
transform: scaleX(1);
/* Menos recomendable en muchos casos */
width: 100%;
Esto no significa que nunca puedas animar otras propiedades, pero sí que deberías hacerlo con cuidado. Si estás trabajando en interfaces complejas, puede ayudarte este artículo sobre animaciones CSS y rendimiento.
Respeta prefers-reduced-motion
La accesibilidad es fundamental. Algunas personas prefieren reducir el movimiento en sus dispositivos porque ciertas animaciones pueden provocar incomodidad, mareo o dificultad para concentrarse.
Puedes ofrecer una alternativa con prefers-reduced-motion:
@media (prefers-reduced-motion: reduce) {
.card,
.hero-image,
.reading-progress {
animation: none;
transform: none;
opacity: 1;
}
}
Este bloque desactiva las animaciones para quienes han configurado esa preferencia en el sistema o en el navegador.
Si quieres profundizar en esta parte, puedes leer la guía sobre prefers-reduced-motion en CSS, especialmente útil cuando trabajas con animaciones en interfaces reales.
Diseña primero una versión sin animación
Una buena experiencia no debería depender por completo de la animación. El contenido debe poder leerse y entenderse aunque el navegador no soporte esta funcionalidad o aunque el usuario haya reducido el movimiento.
Por eso, lo recomendable es trabajar con mejora progresiva. Primero diseña una versión estática, clara y funcional. Después añade las scroll-driven animations como una capa de enriquecimiento visual.
Puedes usar @supports para aplicar estos estilos solo en navegadores compatibles:
@supports (animation-timeline: scroll()) {
.reading-progress {
animation: reading-progress linear both;
animation-timeline: scroll(root block);
}
}
Esta estrategia ayuda a evitar errores y mantiene una experiencia sólida para más usuarios.
Errores comunes al usar animaciones con scroll CSS
Animar demasiados elementos
Uno de los errores más frecuentes es querer animarlo todo. Si cada bloque aparece, se desplaza, escala o cambia de color, la página puede volverse pesada y difícil de leer.
La animación necesita ritmo. Debe aparecer en momentos concretos y con un propósito claro. Si todo se mueve, nada destaca.
No ajustar bien el rango de animación
Otro error habitual es no controlar cuándo empieza y termina el efecto. Si la animación empieza demasiado tarde, puede pasar desapercibida. Si termina demasiado rápido, puede resultar brusca.
animation-range es una herramienta clave para ajustar ese comportamiento. No la trates como un detalle menor: muchas veces, la diferencia entre una animación elegante y una incómoda está precisamente en ese ajuste.
Confundir espectacularidad con buena experiencia
Una animación llamativa puede impresionar durante unos segundos, pero eso no significa que mejore la UX. En una web profesional, las mejores animaciones suelen ser las que acompañan sin interrumpir.
El objetivo no es que el usuario piense “qué animación tan bonita”, sino que la navegación resulte más clara, fluida y comprensible.
Cuándo usar scroll-driven animations
Las scroll-driven animations son especialmente útiles en:
- Artículos largos con barra de progreso.
- Landings con secciones diferenciadas.
- Portfolios visuales.
- Páginas de producto con storytelling.
- Casos de estudio.
- Documentación técnica.
- Bloques que necesitan aparecer de forma progresiva.
- Imágenes o elementos destacados que acompañan el recorrido.
También pueden combinarse con otros recursos de animación CSS, como @keyframes, transiciones suaves y microinteracciones. Si quieres reforzar esa base, puedes consultar la guía sobre @keyframes en CSS.
Cuándo evitarlas
Conviene evitarlas cuando la animación pueda entorpecer la tarea principal. Por ejemplo, en formularios largos, procesos de compra, paneles de gestión o interfaces donde la prioridad sea completar una acción de forma rápida y sin distracciones.
También deberías tener cuidado en páginas visualmente densas. Si ya hay mucho contenido, muchos colores o muchos elementos compitiendo por la atención, añadir movimiento puede aumentar la carga cognitiva.
En estos casos, una experiencia más estática, clara y directa puede ser mucho más eficaz.
FAQs sobre scroll-driven animations
¿Las scroll-driven animations sustituyen a JavaScript?
No siempre. Las scroll-driven animations permiten resolver muchos efectos visuales sin JavaScript, especialmente cuando el objetivo es vincular una animación al progreso del scroll o a la visibilidad de un elemento. Sin embargo, JavaScript sigue siendo necesario para lógica compleja, cambios de estado avanzados, sincronización con datos o interacciones que van más allá de la presentación visual.
¿Puedo usar scroll-driven animations en producción?
Sí, pero con criterio. Lo ideal es usarlas como mejora progresiva, comprobar compatibilidad, respetar prefers-reduced-motion y evitar que una funcionalidad esencial dependa únicamente de ellas. Para barras de progreso, revelados suaves o efectos visuales complementarios, pueden ser una opción muy interesante.
¿Qué diferencia hay entre scroll() y view()?
scroll() vincula la animación al progreso de desplazamiento de un contenedor, como la página completa. Es ideal para barras de progreso o efectos asociados al avance general del scroll. view() vincula la animación a la visibilidad de un elemento dentro del viewport, por lo que resulta muy útil para revelar tarjetas, imágenes o secciones cuando entran en pantalla.
Animar con scroll también es diseñar la experiencia
Las scroll-driven animations representan un paso muy interesante en la evolución de CSS. Nos permiten crear animaciones más conectadas con el comportamiento real del usuario y reducir la dependencia de JavaScript en muchos efectos visuales habituales.
Pero su valor no está en hacer páginas más espectaculares, sino en hacerlas más claras. Una animación vinculada al scroll puede orientar, acompañar la lectura, reforzar una jerarquía visual o convertir una sección larga en una experiencia más fluida. Sin embargo, también puede convertirse en una distracción si se usa sin medida.
La clave está en empezar por casos sencillos: una barra de progreso, una tarjeta que aparece suavemente, una imagen que acompaña el recorrido de una sección. Después, observa si la animación realmente aporta algo. Si ayuda a entender mejor el contenido, tiene sentido. Si solo llama la atención, quizá sea mejor simplificar.
Porque animar bien no significa mover muchas cosas. Significa mover lo justo, en el momento adecuado y con una intención clara.