Demos / Scroll-driven animation

Motion tied to your finger.

The progress bar at the top of the box below is driven by animation-timeline: scroll(self) — no JavaScript, no scroll listener, no requestAnimationFrame. Inside, each slide animates in via animation-timeline: view() when it enters the viewport.

Scroll ↓

This box snaps and animates as you move through it.

No JS

The progress bar above only uses CSS.

No timers

Animations advance with your finger, not the clock.

Snap.

scroll-snap-type: y mandatory holds you on a slide.

How the progress bar works

.scroll-progress {
  animation: progress linear;
  animation-timeline: scroll(self);
  transform-origin: 0 50%;
}
@keyframes progress { to { transform: scaleX(1); } }

scroll(self) says "use my own scroll position as the timeline" — at the top of the scroller the animation is at 0%, at the bottom it's at 100%. view() works the same way but on per-element visibility, so each slide's title can rise as the slide enters view.

Safari shipped both timelines in 2024. On a browser that doesn't support them, the animation simply never advances and the page still works — the progress bar just stays at zero.