Blanche
Blanche Agency

Blanche · Studio

© 2026

The JavaScript Graveyard: How Native CSS Scroll Animations Are Making Your Animation Libraries Obsolete
Back to blog
Motion DesignPerformance OptimizationWeb DevelopmentMay 7, 2026·8 min read

The JavaScript Graveyard: How Native CSS Scroll Animations Are Making Your Animation Libraries Obsolete

The CSS Scroll-Driven Animations API just landed in stable browsers — and it's quietly dismantling the case for GSAP, Framer Motion, and every other JavaScript animation library you've been shipping to users. Here's the performance evidence, the migration patterns, and the honest truth about what JavaScript still does better.

The JavaScript Graveyard: How Native CSS Scroll-Driven Animations Are Making Your Animation Libraries Obsolete

Every few years, the web platform makes a quiet power grab. It absorbed what we were doing with jQuery. It swallowed what we were doing with polyfill-heavy Flexbox hacks. Now, it's coming for your scroll animations — and this time, it has the Compositor thread on its side.

The CSS Scroll-Driven Animations API reached cross-browser stability in late 2023 and has since been sitting in your stylesheet, fully capable, largely underused. If you're still reaching for GSAP or Framer Motion every time a client says "make it scroll nicely," you're shipping kilobytes users didn't ask for to solve problems CSS now owns natively.

This isn't a hit piece on animation libraries. It's a reckoning with the defaults.


What CSS Scroll-Driven Animations Actually Do (And Don't Do)

At its core, the Scroll-Driven Animations spec introduces two new timeline types that replace the document's default time-based progression with scroll position as the animation driver.

  • scroll() — ties an animation's progress to the scroll position of a specific scroll container (or the root viewport). As you scroll down, the animation advances forward.
  • view() — ties progress to an element's position within its scroll container. The animation runs as the element enters and exits the visible area.

You wire these into the existing Web Animations API or pure CSS animation declarations using the animation-timeline property:

.hero-title {
  animation: fade-up linear;
  animation-timeline: scroll(root);
  animation-range: entry 0% entry 40%;
}

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

That's it. No IntersectionObserver. No requestAnimationFrame loop. No event listener cleanup. The browser handles timeline interpolation entirely.

Browser support as of mid-2024: Chrome 115+, Edge 115+, and Firefox 110+ (behind a flag until 132, shipping in stable 2024). Safari is the known laggard — support is partial in Safari 17.2+ but not feature-complete. This means a progressive enhancement strategy is still warranted, but the Chromium baseline alone covers 65–70% of global traffic, which is a legitimate threshold for production adoption.

The @supports escape hatch is your friend: @supports (animation-timeline: scroll()) lets you layer scroll-driven behavior on top of a static fallback without touching a single line of JavaScript.


The Performance Case: Bundle Size, Jank, and Composited Layers

Here's where the argument gets hard to ignore.

Bundle Weight

The most common scroll animation setups in the wild look something like this:

ApproachAdded Bundle Weight
GSAP Core + ScrollTrigger~67 KB minified
Framer Motion (tree-shaken)~43 KB minified
AOS (Animate on Scroll)~13 KB minified
Native CSS Scroll-Driven0 KB

Zero. It's in the browser. You're not shipping the runtime — you're declaring intent, and the platform executes it.

For a typical marketing site with four or five scroll reveal effects, replacing library-driven animations with native CSS is a legitimate 40–70 KB reduction in JavaScript parse and execute cost. On a mid-range Android device on 4G, that's a measurable First Input Delay improvement.

The Compositor Advantage

This is the less-discussed but more important win. JavaScript scroll-linked animations — even well-written GSAP setups — run on the main thread unless you're explicitly using will-change, transform, and opacity in carefully isolated conditions. The main thread also handles your event listeners, your framework re-renders, your third-party scripts.

CSS Scroll-Driven Animations that animate transform and opacity run on the Compositor thread — a dedicated, isolated execution context that doesn't compete for main thread time. The browser's animation engine handles interpolation at the hardware level.

In Chrome DevTools performance traces, scroll-linked GSAP animations on transform properties consistently show up in the main thread flame graph. Native CSS equivalents? They don't appear there at all. They're composited out of the picture entirely.

Translation: Native CSS scroll animations don't just reduce bundle size — they move animation work off the most contentious piece of real estate in browser performance.


Five Scroll Effects You Can Rewrite in Pure CSS Today

1. Fade-In on Scroll (The Most Overused Effect in Web History)

Classic IntersectionObserver + class toggle pattern. Replace it entirely:

.card {
  animation: reveal linear both;
  animation-timeline: view();
  animation-range: entry 10% entry 40%;
}
@keyframes reveal {
  from { opacity: 0; transform: translateY(30px); }
  to   { opacity: 1; transform: translateY(0); }
}

2. Sticky Progress Bar

Document reading progress indicators — a scroll() use case so perfect it feels like the spec was written for it:

#progress-bar {
  position: fixed;
  top: 0;
  width: 100%;
  height: 3px;
  background: var(--accent);
  transform-origin: left;
  animation: grow-bar linear;
  animation-timeline: scroll(root);
}
@keyframes grow-bar {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

No state, no math, no event listener. The browser is the scroll progress calculator.

3. Parallax Hero Sections

.hero-image {
  animation: parallax linear;
  animation-timeline: scroll(root);
  animation-range: cover 0% cover 100%;
}
@keyframes parallax {
  from { transform: translateY(0); }
  to   { transform: translateY(-25%); }
}

4. Horizontal Scroll Carousels Driven by Vertical Scroll

One of the flashiest agency effects — driving a translateX on a horizontal strip as the user scrolls vertically — is fully achievable with scroll() on a pinned wrapper element. The CSS-Tricks approach of using sticky + scroll-timeline handles this without a single line of JavaScript.

5. Image Reveal / Clip-Path Animations on Entry

.image-reveal {
  animation: clip-reveal linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 50%;
}
@keyframes clip-reveal {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0% 0 0); }
}

When JavaScript Animation Libraries Still Earn Their Place

Here's the honest part. CSS Scroll-Driven Animations are not a full replacement for the JavaScript animation ecosystem. There are clear, legitimate use cases where libraries like GSAP remain the right call:

Complex sequencing and timelines. GSAP's Timeline API for chaining tens of interdependent animations with staggering, callbacks, and conditional branching has no CSS equivalent. If your animation resembles a film cut sequence, JavaScript wins.

Physics-based motion. Spring physics, momentum curves, and drag interactions — the domain of Framer Motion's useSpring and libraries like React Spring — aren't reproducible with CSS easing functions alone.

Three.js and WebGL integration. If your scroll is driving 3D scene progression, shader uniforms, or camera movement, you need JavaScript. Full stop.

Dynamic, data-driven animation. When animation parameters come from user input, API responses, or runtime state, you need JavaScript to calculate and apply them. CSS can't interpolate between values it doesn't know at parse time.

Older browser requirements. If your project has meaningful Safari < 17 traffic or needs IE11-era support (please leave), CSS Scroll-Driven Animations aren't production-safe as a primary strategy.

The practical heuristic: If your scroll animation can be fully described at design time and operates on CSS-animatable properties, native CSS should be your default. If it needs to respond to data, state, or user behavior — reach for JavaScript.


The Broader Pattern: CSS Reclaiming Its Territory

Scroll-Driven Animations are part of a decade-long arc of CSS becoming genuinely capable of creative UI work that JavaScript colonized by necessity rather than by right.

  • Custom Properties (2016) → eliminated most JS-driven theming hacks
  • position: sticky (2018) → killed the sticky header plugin industry
  • CSS Grid (2017) → buried most layout JavaScript
  • clamp() and container queries (2020–2022) → made viewport-aware JS calculations largely obsolete
  • Scroll-Driven Animations (2023) → the next frontier claimed

This isn't CSS showing off. It's the platform catching up to what developers had been building workarounds for. Each capability the browser absorbs is compute you stop shipping, dependencies you stop updating, and attack surface you stop exposing.


Choosing the Right Tool for a CSS-First Future

The senior move here isn't to rip GSAP out of every project. It's to raise your justification threshold for reaching for it.

Start from CSS. Scroll-Driven Animations, combined with @starting-style, transition-behavior, and modern easing functions like linear() with custom curves, now cover the vast majority of production scroll effects that agencies and product teams actually ship.

Reach for JavaScript when the animation is dynamic, physics-based, sequenced beyond what CSS timelines support, or needs to integrate with application state. In those cases, GSAP and Framer Motion are worth every byte.

But for the bread-and-butter scroll reveals, progress indicators, parallax layers, and entry animations that make up 80% of "make it feel premium" briefs? Your stylesheet called. It said it's got this.

The JavaScript graveyard isn't filling up overnight — but there's a freshly dug plot with "scroll-linked animation library" on the headstone. Whether you fill it depends entirely on whether you've checked what CSS can do lately.

The JavaScript Graveyard: How Native CSS Scroll Animations Are Making Your Animation Libraries Obsolete | Blanche | Blanche Agency