CSS Scroll-Driven Animations

Share
Scroll-driven CSS animations: cards revealing, parallax layers, and a pure-CSS carousel

Scroll-Driven Animations in CSS: Building Smooth Effects Without JavaScript

For years, scroll-based animations on the web have been the domain of JavaScript. Libraries like GSAP and ScrollMagic dominated the space, and even simple effects required addEventListener('scroll'), IntersectionObserver, or manual scroll position tracking. But in 2026, that's changing rapidly. CSS scroll-driven animations — powered by the Animation Timeline API — now ship across all major browsers, enabling performant scroll-linked effects with zero JavaScript.

In this post, we'll explore what scroll-driven animations are, how they work, and practical patterns you can use today to replace scroll-heavy JavaScript with pure CSS.

What Are Scroll-Driven Animations?

CSS scroll-driven animations allow you to link an animation's progress directly to the user's scroll position instead of time. Instead of an animation playing over five seconds, it plays as the user scrolls through a specific section of the page. The animation advances based on the scroll timeline, not wall-clock time.

This is powered by two key CSS properties:

  • animation-timeline — specifies which scroll position drives the animation
  • view-timeline-name — defines a named timeline on an element that other elements can reference

The result is buttery smooth animations that run on the compositor thread, avoiding layout thrashing and JavaScript main-thread blocking entirely.

Browser Support in 2026

As of mid-2026, scroll-driven animations have broad support:

  • Chrome/Edge 115+ — full support
  • Firefox 118+ — full support (enabled by default since version 124)
  • Safari 17.4+ — full support

This means over 90% of global browser traffic is covered. The right strategy is progressive enhancement: provide a polished animated experience for users on supported browsers, and a functional, non-animated fallback for the rest.

Basic Pattern: Reveal on Scroll

The simplest use case is fading or sliding elements into view as they enter the viewport. Here's how it works with CSS:

.reveal-card {
  opacity: 0;
  transform: translateY(40px);
  animation: reveal linear forwards;
  animation-timeline: view();
  animation-range: entry 25% cover 40%;
}

@keyframes reveal {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

The view() shorthand creates a view timeline tied to the element itself. The animation-range property controls when the animation starts and ends — here, it begins when 25% of the element enters the viewport and completes when 40% is visible. This gives you fine-grained control over timing without any scroll event listeners.

One of the most impressive use cases in 2026 is building carousels entirely in CSS. Using scroll-timeline on a container and mapping it to child element animations, you can create horizontal scrolling galleries:

.carousel-track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
}

.carousel-slide {
  animation: slide-progress linear forwards;
  animation-timeline: --carousel-scroll;
  animation-range: cover 0% cover 100%;
}

.carousel-track::before {
  content: '';
  view-timeline-name: --carousel-scroll;
  view-timeline-axis: inline;
}

The key insight is using view-timeline-name on a pseudo-element of the container to expose a scroll timeline, which child elements then reference with animation-timeline. Combined with scroll-snap-type, this creates a polished carousel experience that requires zero JavaScript.

Advanced Pattern: Parallax Effects

Parallax scrolling — where background elements move at different speeds than foreground content — is another classic use case. With scroll-driven animations, it becomes trivial:

.parallax-bg {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 120%;
  animation: parallax linear forwards;
  animation-timeline: scroll(root);
}

@keyframes parallax {
  to {
    transform: translateY(-20%);
  }
}

The scroll(root) timeline is linked to the document's scroll position rather than a specific element. As the user scrolls, the background shifts proportionally, creating depth without any JavaScript calculations.

Animation Range: The Secret Sauce

The animation-range property is what makes scroll-driven animations truly powerful. It lets you control exactly when an animation starts and ends relative to the scroll position:

  • entry 0% cover 50% — starts when the element first enters, completes halfway through
  • contain 0% contain 100% — triggers based on the element's container instead of viewport
  • cover 25% cover 75% — animation plays as the element moves from 25% to 75% coverage

This granularity means you can choreograph complex multi-element scroll sequences. Each element can have its own range, creating a cascading effect across the page.

Fallback Strategy

For browsers that don't support scroll-driven animations, the content remains fully functional — it just doesn't animate. You can add a feature query to provide enhanced fallbacks:

@supports (animation-timeline: view()) {
  .reveal-card {
    opacity: 0;
    transform: translateY(40px);
    animation: reveal linear forwards;
    animation-timeline: view();
  }
}

This ensures graceful degradation while still delivering the best experience to modern browsers.

Performance Benefits

Beyond the simplicity of pure CSS, scroll-driven animations offer significant performance advantages:

  • Compositor-only execution — animations run on the GPU thread, never blocking the main thread
  • No memory leaks — no event listeners to clean up or requestAnimationFrame loops to stop
  • Battery efficient — the browser optimizes scroll timeline updates internally
  • Zero bundle size — unlike GSAP, ScrollTrigger, or other animation libraries

When to Use JavaScript Instead

CSS scroll-driven animations aren't a replacement for all scroll logic. You still need JavaScript when:

  • You need to trigger non-visual side effects (API calls, analytics)
  • You want complex physics-based interactions with momentum and easing beyond CSS keyframes
  • You need to detect scroll direction or implement infinite scroll loading
  • You must support older browsers as a primary target without progressive enhancement

For visual effects tied to scroll position, though, CSS is now the clear winner.

Conclusion

CSS scroll-driven animations represent a significant milestone in web development. What once required heavy JavaScript libraries can now be expressed declaratively in CSS — with better performance and less code. As browser support continues to grow through 2026, this API will become the default approach for scroll-based visual effects on the web.

The time to start experimenting is now. Even if you add a scroll-timeline-polyfill for older browsers, the CSS-first approach gives you a solid foundation that only improves as users upgrade.