← Back to Lesson

🎢 Scroll-Driven Animations

Scroll to Explore

Modern CSS scroll-driven animations

📊 What Are Scroll-Driven Animations?

Scroll-driven animations are a new CSS feature that lets animations progress based on scroll position instead of time. This creates performant, native parallax effects, progress indicators, and reveal animations without JavaScript.

⚡ Performance Benefits

Unlike JavaScript scroll listeners, CSS scroll-driven animations run on the compositor thread, providing buttery-smooth 60fps performance. The browser optimizes these animations automatically.

🎯 Browser Support

Currently supported in Chrome/Edge 115+, with Firefox and Safari implementing. Use @supports for progressive enhancement and provide JavaScript fallbacks for older browsers.

Sticky Section

This section scales in and out as it enters and exits the viewport using animation-timeline: view() . Scroll down to see it stick and then continue past it.

📝 Code Examples

1. Progress Bar

.progress-bar {
  position: fixed;
  top: 0;
  height: 4px;
  background: linear-gradient(...);
  transform-origin: left;
}

@supports (animation-timeline: scroll()) {
  .progress-bar {
    animation: progressGrow linear;
    animation-timeline: scroll();
  }

  @keyframes progressGrow {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
  }
}

2. Parallax Background

@supports (animation-timeline: scroll()) {
  .hero-bg {
    animation: heroParallax linear;
    animation-timeline: scroll();
  }

  @keyframes heroParallax {
    to { transform: translateY(50vh); }
  }
}

3. Fade In on Scroll (View Timeline)

@supports (animation-timeline: view()) {
  .content-card {
    animation: fadeInView linear;
    animation-timeline: view();
    animation-range: entry 0% cover 30%;
  }

  @keyframes fadeInView {
    from {
      opacity: 0;
      transform: translateY(50px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
}

4. JavaScript Fallback

if (!CSS.supports('animation-timeline: scroll()')) {
  const progress = document.getElementById('progressBar');

  window.addEventListener('scroll', () => {
    const scrolled = window.scrollY;
    const total = document.body.scrollHeight - window.innerHeight;
    const percent = scrolled / total;
    progress.style.transform = `scaleX(${percent})`;
  }, { passive: true });
}