TL;DR: CSS Scroll-Driven Animations let you animate elements based on scroll position – entirely without JavaScript. With animation-timeline: scroll() and animation-timeline: view(), you can build progress bars, fade-ins, and parallax effects in pure CSS. Performant, elegant, and future-proof.

🤔 What Are Scroll-Driven Animations?

Imagine scrolling through a website and elements move, fade in, or transform – all perfectly synced to your scroll position. Sounds like a lot of JavaScript? Not anymore.

CSS Scroll-Driven Animations are a new CSS specification that lets you tie existing CSS animations to scroll progress. Instead of a time-based animation, the animation runs as fast or slow as you scroll. No requestAnimationFrame, no IntersectionObserver, no event listeners. Pure CSS.

There are two main concepts:

  • Scroll Progress Timeline – The animation is tied to the overall scroll progress of a container.
  • View Progress Timeline – The animation starts and ends when an element scrolls into the viewport.

🕰️ The Old Way: JavaScript and IntersectionObserver

Until now, the standard approach for scroll-based animations was a mix of JavaScript and CSS. You'd either use a scroll event listener or the IntersectionObserver to toggle classes.

Intersection Observer: A powerful tool for efficient web design 🚀
Learn how the Intersection Observer works and why CSS Scroll-Driven Animations can partially replace it.

A typical example looked something like this:

// The old way with IntersectionObserver
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('visible');
    }
  });
}, { threshold: 0.1 });

document.querySelectorAll('.animate-on-scroll').forEach(el => {
  observer.observe(el);
});
/* Plus the CSS class */
.animate-on-scroll {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.6s, transform 0.6s;
}

.animate-on-scroll.visible {
  opacity: 1;
  transform: translateY(0);
}

This works. But it has downsides: you need JavaScript, the animation isn't truly tied to scroll position (it only triggers once), and with many elements, performance can suffer.

🚀 The New Way: Pure CSS with animation-timeline

Here's where it gets exciting. With CSS Scroll-Driven Animations, you only need CSS. The key is two new properties:

  • animation-timeline: scroll() – Ties the animation to scroll progress.
  • animation-timeline: view() – Ties the animation to an element's visibility in the viewport.

scroll() – The Scroll Progress Timeline

With scroll(), you tell the browser: "Hey, use the scroll progress as the timeline for this animation." The function accepts two optional parameters:

animation-timeline: scroll(<scroller> <axis>);

/* Examples */
animation-timeline: scroll();              /* nearest scrollable ancestor, block axis */
animation-timeline: scroll(root);          /* the root element (viewport) */
animation-timeline: scroll(nearest);       /* nearest scrollable ancestor */
animation-timeline: scroll(root inline);   /* root element, inline axis */

view() – The View Progress Timeline

view() is perfect for elements that should animate when they scroll into the visible area. Think fade-ins, slide-ins, or scale effects.

animation-timeline: view();
animation-timeline: view(block);           /* block axis (default) */
animation-timeline: view(inline);          /* inline axis */
animation-timeline: view(block 50px);      /* with inset */

🎯 Practical Example 1: Scroll Progress Bar

A classic example: a progress bar at the top of the page showing how far you've scrolled. This used to require JavaScript. Now? Three CSS rules.

.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  height: 4px;
  background: linear-gradient(to right, #6366f1, #8b5cf6);
  transform-origin: left;

  /* The magic */
  animation: grow-progress linear;
  animation-timeline: scroll(root);
}

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

That's it. No JavaScript. The bar scales automatically based on your scroll position. Smooth, performant, and declarative.

Size specifications in CSS: A developer's joys and sorrows
CSS units like vh, vw and friends also play a role in Scroll-Driven Animations.

🎯 Practical Example 2: Fade-In on Scroll

Want elements to fade in as they scroll into view? With view(), it's a breeze:

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

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

The element starts invisible and fades in as it enters the viewport. animation-range: entry 0% entry 100% means: the animation runs during the entire "entry" phase – from the first pixel until the element is fully visible.

🎯 Practical Example 3: Parallax Effect

Parallax effects used to be a JavaScript nightmare. Now you can do it in pure CSS:

.parallax-element {
  animation: parallax linear both;
  animation-timeline: view();
}

@keyframes parallax {
  from {
    transform: translateY(-50px);
  }
  to {
    transform: translateY(50px);
  }
}

The element moves slower than the rest of the page. Subtle, elegant, and without a single line of JavaScript.

🎚️ animation-range: Precise Control

The real power lies in animation-range. It lets you control exactly when the animation should start and end. There are several named ranges:

RangeDescription
entryElement enters the viewport
exitElement exits the viewport
containElement is fully visible
coverFrom first to last visible pixel
/* Only animate during entry */
animation-range: entry;

/* Only the first 50% of entry */
animation-range: entry 0% entry 50%;

/* From entry to exit */
animation-range: entry 0% exit 100%;

/* Only when fully visible */
animation-range: contain;

/* With fixed values */
animation-range: entry 20px entry 200px;

This gives you incredibly fine-grained control over your animations. For example, an element that only fades in during the first half of entry and then stays put.

⚙️ @keyframes in a Scroll Context

Important point: your @keyframes work exactly the same as always. The only difference is that the timeline isn't measured in seconds but in scroll progress (0% to 100%).

@keyframes reveal {
  0% {
    opacity: 0;
    transform: scale(0.8) rotate(-5deg);
    filter: blur(10px);
  }
  50% {
    opacity: 1;
    filter: blur(0);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}

.reveal-element {
  animation: reveal linear both;
  animation-timeline: view();
  animation-range: entry;
}

The beauty of it: you can define complex, multi-step animations that perfectly adapt to scroll position. Everything stays declarative and predictable.

🌐 Browser Support and Progressive Enhancement

As of March 2026, browser support is looking pretty solid. Chrome and Edge have supported Scroll-Driven Animations since version 115. Firefox has had them enabled by default since version 131. Safari supports them in newer versions as well.

Still, you should use progressive enhancement. The @supports rule is your best friend:

/* Base styling without animation */
.element {
  opacity: 1;
  transform: none;
}

/* Scroll animation only when supported */
@supports (animation-timeline: view()) {
  .element {
    animation: fade-in linear both;
    animation-timeline: view();
    animation-range: entry;
  }
}

This way your site works everywhere – with animations where possible, without as a fallback. No user sees a broken page.

CSS scroll-driven animations - CSS | MDN
The official MDN documentation for CSS Scroll-Driven Animations.
Animate elements on scroll with Scroll-driven animations
Google Chrome's comprehensive guide to scroll-driven animations in CSS.

⚡ Performance: CSS vs. JavaScript

Why is the CSS approach better? Simple:

  • Main thread stays free: CSS animations run on the compositor thread. JavaScript-based animations block the main thread.
  • No layout thrashing: The browser optimizes CSS animations automatically. With JS, you have to manage that yourself.
  • Less code: No JavaScript bundle that needs to be loaded and parsed.
  • Automatic optimization: The browser can automatically throttle CSS animations when they're not visible.

In my testing, the difference on pages with many animated elements was clearly noticeable. Less jank, smoother animations, better Core Web Vitals.

💡 Conclusion

CSS Scroll-Driven Animations are a game changer. What used to require dozens of lines of JavaScript now works with a handful of CSS properties. The API is intuitive, performance is excellent, and browser support has become solid.

My tip: start with the scroll progress bar. It's the simplest example and you'll immediately see how powerful this is. Then experiment with view() and animation-range for fade-ins and reveal effects.

The future of web animations is declarative. And it's here now.

Artikel teilen:Share article:

Discover more articles

CSS Scroll-Driven Animations – Animationen ohne JavaScript 🎬
Previous article

CSS Scroll-Driven Animations – Animationen ohne JavaScript 🎬

TL;DR: CSS Scroll-Driven Animations ermöglichen es dir, Elemente basierend auf der Scroll-Position zu animieren – ganz ohne JavaScript. Mit animation-timeline: scroll() und animation-timeline: view() kannst du Fortschrittsbalken, Fade-Ins und Parallax-Effekte rein deklarativ umsetzen. Performant, elegant und zukunftssicher. 🤔 Was sind Scroll-Driven Animations? Stell dir vor, du scrollst durch eine Website und

5 min read 17. Mai 2026
CSS Grid: The Missing Counterpart to Flexbox 🧩
Similar article

CSS Grid: The Missing Counterpart to Flexbox 🧩

TL;DR: CSS Grid is the missing puzzle piece to your Flexbox knowledge. While Flexbox handles one-dimensional layouts, Grid gives you full control over rows AND columns simultaneously. This article covers everything from basics to subgrid – with practical examples you can use right away. You know Flexbox? Great. Time to

4 min read 15. Mai 2026
View Transitions API: Smooth Page Transitions Without a Framework ✨
Similar article

View Transitions API: Smooth Page Transitions Without a Framework ✨

TL;DR: The View Transitions API brings buttery-smooth page transitions directly to the browser - no framework, no JavaScript library needed. Just CSS and a few lines of JS. Here's how it works and why you should start using it today. 🤔 What Are View Transitions Anyway? You know

6 min read 13. Mai 2026
CSS :has() – The Parent Selector Everyone’s Been Waiting For 🎯
Similar article

CSS :has() – The Parent Selector Everyone’s Been Waiting For 🎯

TL;DR: CSS :has() is the long-awaited parent selector – you can finally style parent elements based on their children. No more JavaScript hacks, no workarounds, just pure CSS. And yes, it works in all modern browsers. 🤔 Why CSS Never Had a Parent Selector If you've been writing CSS

4 min read 27. Apr. 2026
Container Queries in CSS: The End of Media Queries? 📦
Similar article

Container Queries in CSS: The End of Media Queries? 📦

Container Queries put an end to viewport chaos! 📦 How to make your components truly responsive – and why Media Queries are not dead yet.

5 min read 14. März 2026