Scroll-driven Animation
滚动驱动动画
Aliases:滚动驱动动画滚动动画随滚动动滑到哪动到哪scroll animationscroll-drivenscroll-linked animation
What is it
Animation progress is tied to scroll position rather than time: scrub to where you want, even backwards. It powers scroll-linked progress bars, scroll-unfurled storytelling and parallax layers. Unlike scroll reveal it does not play once after a trigger — scroll position scrubs the timeline.
Interactive playground
Try it. Make an informed choice.Loading demo…
✓ When to use
- Narrative unfurls with reading and must stay in sync with scroll
- Scroll progress or reading-depth feedback is needed
- Spatial layering — parallax planes, sticky chapters
✕ When not to use
- Users scroll straight to content — animation slows arrival
- Nested scrollers where progress ownership is ambiguous
- A single entrance is enough — plain scroll reveal is simpler
Variants
Scroll-linked
滚动联动
Progress maps straight to scroll — scrubbable both ways
Scroll-triggered
滚动触发
Fires past a threshold then plays on a clock, not on scroll
Parallax layers
视差层
Layers move at different rates to fake depth
Implementation
animation-timeline: scroll()animation-rangetransform: translateYprogressPrefer CSS: animation-timeline: scroll() with animation-range binds keyframes to scroll progress; where unsupported, a JS scroll listener writes a CSS variable (e.g. --scroll) that calc drives transform/opacity. Any timed portion of a triggered animation must still use calc(<duration> * var(--demo-speed, 1)). Make scroll listeners passive and rAF-throttled. Respect prefers-reduced-motion by landing on the final state.
Platform API
animation-timeline: scroll()scroll()Intersection ObserverAgent prompts
Four prompt layers run from “what it is” all the way to a ready-to-run task. On the Agent task layer you can stack a visual style and extra requirements, then copy it to your coding agent in one click.
Implement scroll-driven animation in the current project. Inspect the existing component system and design tokens first; reuse existing components. Keep the project's visual style. Add no unnecessary dependencies. Requirements: - Progress bound to scroll position and reversible - Prefer animation-timeline: scroll() with a JS fallback - Timed animation durations written calc(<duration> * var(--demo-speed, 1)) - Respect prefers-reduced-motion Run existing project checks when done and list the modified files. Additional requirements: - Dark mode support - Respect prefers-reduced-motion - No new dependencies - Run existing checks and list modified files
Hand to your coding agent — stack a style and extra requirements on top
Related concepts
Elements stay hidden until they enter the viewport, then play a fade, rise or slide-in — once. It replaces "dump everything at once" with content revealed at the pace of reading, giving long pages a sense of order. Usually triggered by IntersectionObserver.
MotionAlternativeOn scroll, layers move at different speeds — background slower, foreground faster — and the velocity gap reads as depth. The cheapest way to fake 3D in 2D; a staple of hero sections and scrollytelling.
MotionAlternativeReveals a headline line by line or word by word instead of fading the whole block in. The spoken-rhythm staggering gives copy order and weight — a staple of landing-page hero titles, section intros and scrollytelling, usually triggered once on entering the viewport.
MotionUsed with