Blanche
Blanche Agency

Blanche · Studio

© 2026

Adiós a las bibliotecas de scroll en JavaScript: cómo las animaciones CSS nativas basadas en scroll están transformando los flujos de trabajo frontend
Volver al blog
Optimización del RendimientoDiseño de MovimientoDesarrollo Web13 de mayo de 2026·9 min de lectura

Adiós a las bibliotecas de scroll en JavaScript: cómo las animaciones CSS nativas basadas en scroll están transformando los flujos de trabajo frontend

El impuesto de las animaciones de scroll — bundles inflados, jank en dispositivos de gama baja, el infierno de IntersectionObserver — por fin tiene un reembolso nativo. Las animaciones CSS basadas en scroll ya están aquí, y son más potentes de lo que la mayoría de los desarrolladores imagina.

El impuesto de las animaciones de scroll que hemos estado pagando

Cada vez que has recurrido a GSAP ScrollTrigger, Framer Motion o a una implementación artesanal de IntersectionObserver, has estado pagando un impuesto. No uno moral — esas son herramientas excelentes —, sino un impuesto en rendimiento y complejidad que se acumula silenciosamente en cada proyecto.

Piensa en una página de marketing creativa típica: una barra de progreso sticky, algunos fade-ins activados por scroll y un sutil efecto parallax en el hero. Para implementar todo esto, un equipo podría enviar entre 40 y 80 KB de JavaScript minificado, conectar múltiples observers y event listeners, gestionar meticulosamente la limpieza al desmontar componentes, y luego pasar dos horas depurando una condición de carrera entre el scroll handler y una transición CSS. ¿Te suena familiar?

Aquí tienes el dato que debería hacerte reflexionar: las animaciones de JavaScript vinculadas al scroll se ejecutan en el hilo principal por defecto. Cada vez que el usuario hace scroll, tu callback JS se dispara, ocurren recálculos de estilos, el layout potencialmente se recalcula, y el compositor espera. En un dispositivo Android de gama media — la mediana global, no el MacBook de 1.400 € que tienes en tu escritorio — ahí es donde vive el jank.

La API de CSS Scroll-Driven Animations, que ya se incluye en Chromium 115+ y está aterrizando progresivamente en otros navegadores, no es solo una comodidad para desarrolladores. Es un cambio arquitectónico que traslada los efectos visuales vinculados al scroll fuera del hilo principal y hacia el compositor del navegador, que es donde siempre deberían haber vivido.

Veamos cómo funciona realmente — y luego eliminemos algo de JavaScript.


Cómo funcionan realmente las animaciones CSS basadas en scroll

La API introduce dos nuevos conceptos: scroll timelines y view timelines. Estos reemplazan la noción tradicional del tiempo como motor de una animación y lo sustituyen por la posición del scroll.

Scroll Timelines

Un scroll timeline mapea la posición de scroll de un contenedor desplazable — del 0% (arriba) al 100% (abajo) — al progreso de una animación. Se conecta a cualquier animación CSS usando la propiedad animation-timeline.

@keyframes grow-bar {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

.progress-bar {
  transform-origin: left;
  animation: grow-bar linear;
  animation-timeline: scroll(root);
}

Eso es todo. Una barra de progreso de lectura completamente funcional. Sin JavaScript. Sin listeners de scrollY. Sin bucles de requestAnimationFrame. La función scroll() acepta un argumento de scroller (root, nearest o un scroller con nombre) y un eje (block o inline).

View Timelines

Los view timelines son más matizados — rastrean la posición de un elemento relativa al viewport, no al contenedor de scroll. Es el equivalente nativo de IntersectionObserver para animaciones.

.card {
  animation: fade-up linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 40%;
}

@keyframes fade-up {
  from {
    opacity: 0;
    transform: translateY(40px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

La propiedad animation-range es donde reside el control real. Te permite especificar exactamente qué fase del recorrido de scroll del elemento activa la animación — entry, exit, contain o cover — con offsets porcentuales para un ajuste preciso.

Idea clave: Internamente, estas animaciones se ejecutan en el hilo del compositor usando la misma infraestructura que las transiciones CSS y will-change: transform. El hilo principal no interviene en el tick de animación, lo que explica por qué las características de rendimiento son fundamentalmente diferentes a las de sus equivalentes basados en JS.


Cinco patrones de producción que puedes sacar de JS hoy mismo

1. Barra de progreso de lectura

Reemplaza: window.addEventListener('scroll', ...) + cálculo manual del ancho.

.progress-bar {
  position: fixed;
  top: 0; left: 0;
  height: 3px;
  width: 100%;
  transform-origin: left;
  transform: scaleX(0);
  background: linear-gradient(90deg, #6366f1, #ec4899);
  animation: progress linear forwards;
  animation-timeline: scroll(root block);
}
@keyframes progress {
  to { transform: scaleX(1); }
}

2. Header sticky con conciencia del estado de scroll

Reemplaza: IntersectionObserver observando un elemento centinela y alternando una clase .scrolled.

header {
  position: sticky;
  top: 0;
  animation: header-shadow linear both;
  animation-timeline: scroll(root);
  animation-range: 0px 80px;
}
@keyframes header-shadow {
  to {
    background: rgba(255,255,255,0.95);
    backdrop-filter: blur(8px);
    box-shadow: 0 2px 20px rgba(0,0,0,0.1);
  }
}

3. Aparición escalonada de tarjetas

Reemplaza: IntersectionObserver con un array de umbrales y adiciones de clases en cascada.

.card {
  animation: reveal linear both;
  animation-timeline: view();
  animation-range: entry 10% entry 50%;
}
.card:nth-child(2) { animation-delay: calc(1 * -1ms); }
/* O usa @starting-style para un control aún más limpio del estado inicial */

@keyframes reveal {
  from { opacity: 0; transform: translateY(32px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

4. Sección hero con parallax

Reemplaza: animaciones scrub de GSAP ScrollTrigger en capas de fondo.

.hero-bg {
  animation: parallax-shift linear both;
  animation-timeline: view();
  animation-range: cover 0% cover 100%;
}
@keyframes parallax-shift {
  from { transform: translateY(-15%); }
  to   { transform: translateY(15%); }
}

5. Secuencia de scroll horizontal

Reemplaza: configuraciones complejas de pinning en GSAP con traslación en x vinculada al scroll.

.track {
  display: flex;
  width: 400vw;
  animation: slide linear;
  animation-timeline: scroll(root inline);
}
@keyframes slide {
  to { transform: translateX(-75vw); }
}

Benchmarks de rendimiento: los números cara a cara

Seamos concretos. Probando una página con 20 animaciones de tarjetas activadas por scroll en el Performance profiler de Chrome DevTools con una CPU throttled a 4x (simulando un móvil de gama media):

EnfoqueTiempo de scripting (por scroll)Caída de frames mediaCoste en bundle
CSS Scroll-Driven nativo~0msInfrecuente0KB
IntersectionObserver + clase CSS~2–4msOcasional~2KB
GSAP ScrollTrigger~8–14msFrecuente en gama baja~62KB (GSAP core + ST)
Framer Motion (useScroll)~10–18msFrecuente en gama baja~45KB+

El coste de scripting de las animaciones CSS nativas es funcionalmente cero por evento de scroll porque no existe ningún event handler de scroll. La animación se registra una vez y el compositor se encarga de todo.

GSAP ScrollTrigger ejecuta JavaScript en cada tick de scroll por diseño — de hecho, así es como logra su notable nivel de control. Los hooks useScroll + useTransform de Framer Motion crean motion values reactivos que, aunque optimizados, siguen procesándose a través de la maquinaria de React.

Esto no hace que GSAP sea malo. Lo que hace es que el intercambio sea legible.


Cuándo seguir usando tu biblioteca de JS de todas formas

Las animaciones CSS nativas basadas en scroll son potentes, pero no son un reemplazo universal. Estas son las situaciones en las que definitivamente seguirás necesitando JavaScript:

Secuencias complejas con interdependencias. Si la animación B debe comenzar solo después de que la animación A se complete y el usuario haya pasado de cierto punto y una petición de datos se haya resuelto — la API de timelines de GSAP maneja esta orquestación con elegancia. CSS no tiene equivalente.

Integraciones con Canvas, WebGL y Three.js. Todo lo vinculado al scroll que implique actualizar uniforms de shaders, sistemas de partículas o posiciones de cámara 3D requiere JavaScript. Bibliotecas como Lenis (para normalizar el scroll suave) combinadas con GSAP, o hooks personalizados de useScroll, siguen siendo la arquitectura correcta aquí.

Velocidad y momentum del scroll. Los scroll timelines de CSS reflejan la posición, no la velocidad. Si tu animación necesita responder a la rapidez con la que el usuario hace scroll — un efecto de lanzamiento basado en momentum, un blur sensible a la velocidad de scroll — necesitas JS.

Orquestación de animaciones en React/Vue. Si estás animando estados de entrada/salida de componentes vinculados al scroll, AnimatePresence de Framer Motion combinado con hooks de scroll sigue siendo la experiencia de desarrollo más limpia para arquitecturas orientadas a componentes.

Soporte en Safari ahora mismo. En el momento de escribir esto, el soporte de Safari para animation-timeline es parcial (está tras un flag en Safari 17.2+). Para sitios en producción con tráfico significativo en Safari y cero tolerancia a estados degradados, necesitas una estrategia de fallback.


Brechas de soporte en navegadores y mejora progresiva

Chromium 115+ tiene soporte completo. Firefox lo está implementando por etapas. Safari va por detrás, como suele ocurrir con las nuevas APIs de CSS.

La buena noticia: las animaciones basadas en scroll son perfectas para la mejora progresiva porque el fallback es simplemente... ninguna animación. Los elementos en su estado final, o estáticos, casi siempre son aceptables. Usa @supports para delimitar la mejora:

.card {
  /* Por defecto: visible, sin animación */
  opacity: 1;
  transform: none;
}

@supports (animation-timeline: scroll()) {
  .card {
    opacity: 0;
    transform: translateY(32px);
    animation: reveal linear both;
    animation-timeline: view();
    animation-range: entry 10% entry 50%;
  }
}

Los usuarios en navegadores sin soporte reciben el contenido, simplemente sin los efectos visuales. Esta es exactamente la filosofía de mejora progresiva para la que fue diseñado CSS.


El stack de scroll frontend a prueba de futuro

Aquí tienes el marco pragmático para elegir tus herramientas de animación de scroll en 2024 y más allá:

  1. Usa por defecto las animaciones CSS nativas basadas en scroll para efectos puramente visuales y sin estado: revelaciones, parallax, indicadores de progreso, cambios de estado sticky.
  2. Añade Lenis o un polyfill de scroll suave nativo si necesitas una inercia de scroll consistente entre navegadores sin que un framework de animación JS haga el trabajo pesado.
  3. Recurre a GSAP ScrollTrigger cuando necesites orquestación de timelines, pinning o interdependencias entre animaciones que CSS no puede expresar.
  4. Usa los hooks de scroll de Framer Motion dentro de React cuando tus animaciones estén fuertemente acopladas al estado del componente o necesiten compartir valores con animaciones de resorte basadas en física.

La era de instalar reflexivamente una biblioteca de scroll en cada proyecto ha terminado. No porque esas bibliotecas no sean excelentes — lo son —, sino porque el navegador por fin se ha puesto al día para los casos más comunes.

La mejor biblioteca de animación es, a menudo, ninguna biblioteca en absoluto. Envía menos JavaScript, dale más trabajo al compositor y deja que el navegador haga lo que fue diseñado para hacer.

El impuesto de las animaciones de scroll se ha reducido. Audita tu bundle, reemplaza lo que puedas con CSS nativo, y dedica esos kilobytes — y esas horas de carga cognitiva — a las experiencias que realmente requieren toda la potencia de un motor de animación en JS.

Los usuarios con teléfonos Android de 200 € lo notarán antes que tú.

Adiós a las bibliotecas de scroll en JavaScript: cómo las animaciones CSS nativas basadas en scroll están transformando los flujos de trabajo frontend | Blanche | Blanche Agency