- Scene
- 12
- Take
- 01
- Level
- Intermediate
- Runtime
- ~3 h
Scroll-Driven and Scroll-Triggered Animation
Let the scroll bar drive an animation, or let scrolling start one: scroll() and view() timelines, ranges, named timelines, the JavaScript API, IntersectionObserver, Lenis, and a calm story section for the Volt.
Most animations so far run on the clock. This phase gives you a second clock, the scroll bar: a scroll-driven animation has no duration in seconds, and its progress is a scroll position, so scrolling back plays it back and stopping freezes it.
You learn the two timelines (scroll() for a scroller, view() for one element crossing the screen), the ranges entry, contain, exit and cover, named timelines and timeline-scope, the JavaScript API, and the other kind: the scroll-triggered animation, where reaching a point starts a normal timed one. You also meet sticky storytelling and smooth-scroll libraries.
Every example has its own small scroller (height: 140px; overflow: auto). At the end the Volt page gets a reading bar, a story whose features fade in, a fallback for browsers without the feature, and a switch-off for reduced motion.
Scene 12 · the brief from Lumen
Ama, head of design at Lumen Bikes
“The page is a long list of sections. I want people to feel they are moving through the Volt's story, without a gimmick that makes anyone feel sick.”
The launch page has feedback on every press, a toast, a cart, a drawer and a filterable gallery. It lacks a story. Tomás, the founder, wants four lines that tell it while people scroll.
Mei storyboards a thin orange bar across the top that fills as you read, and four features that fade in one by one. Kofi says the browser can tie an animation to the scroll bar, with no scroll listener. Lena asks what happens in a browser that cannot, and on her cheap phone.
Ravi has one request: anything that moves with scrolling must stop when he asks for less motion, and the story must read fine with it all off. By the end of this phase the page has the bar and the reveal, a fallback for older browsers, and a switch-off that follows the Phase 7 toggle.
In this scene
You will learn
- Drive an animation from the scroll bar with
scroll()andview(), and choose its range - Name a timeline and share it with
timeline-scope, or create one in JavaScript - Start a timed animation when something enters view, with
IntersectionObserver - Build the Volt story: a reading bar, a reveal, a fallback and a reduced-motion switch-off
You write code in
In your lumen-motion project (npm run dev) and in the editor on this page
Files you touch
- src/styles/scroll.css
- index.html
- src/js/main.js
Shot list · 7 shots, widths by reading time
- 12.1Scroll Progress TimelinesA scroll progress timeline ties an animation to how far a scroller has scrolled: 0% at the top, 100% at the end.
animation-timeline: scroll()does it in one line, with no scroll listener, and the animation has no duration in seconds. 20 min 2 live - 12.2View Progress Timelines and RangesA view progress timeline measures how far one element has travelled across its scroller's visible area.
animation-timeline: view()makes it, andanimation-rangechooses the part of the journey (entry, contain, exit or cover) over which the animation plays. 21 min 3 live - 12.3Named Timelines and timeline-scopeA timeline can have a name, so any element can use it.
scroll-timeline-nameandview-timeline-namecreate the name,animation-timeline: --nameuses it, andtimeline-scopemakes a name visible outside the subtree where it was made. A misspelled name raises no error. 19 min 2 live - 12.4Scroll Timelines in JavaScript
new ScrollTimeline({ source })andnew ViewTimeline({ subject })make the same timelines from JavaScript, andelement.animate(keyframes, { timeline, rangeStart, rangeEnd })plays an animation on them. Use it for animations created at run time, and test for support first. 20 min 2 live - 12.5Scroll-Triggered AnimationA scroll-triggered animation is an ordinary timed animation that starts when scrolling reaches a point.
IntersectionObserveris the tool every browser has, and CSStimeline-triggeris the newer way, still not safe to depend on. 22 min 3 live - 12.6Sticky Storytelling and Smooth ScrollingScrollytelling pins a stage with
position: stickywhile steps scroll past it, and an observer says which step is current. Smooth-scroll libraries such as Lenis replace the browser's scrolling with their own, which is why they are controversial. 19 min 2 live - 12.7Build: The Volt Scroll StorybuildGive the launch page a reading bar and a story section whose four features fade in as they arrive, both driven by the scroll bar in CSS, with an IntersectionObserver fallback for browsers without
view(), and all of it off for reduced motion and the site toggle. 78 min 2 live
Dailies · 5 checked exercises
A film crew watches the day's shots every evening. Build each one yourself and press Check: the page freezes its clock and checks your motion at exact moments, its cost, and its reduced-motion version.
view() timeline over entry, with opacity and transform only. With reduced motion the cards must simply be visible, with no animation.IntermediateD03Share a scroller's timelineThe meter under the box should follow the box's scroll, but it is full from the start. There are two problems, and the console is silent about both. Fix them: empty at the top, half full half way, full at the end.IntermediateD04Reveal cards created by codeAdd appends a card and Remove removes the last one. Give each new card a reveal on its own ViewTimeline (from entry 0% to entry 100%), after testing that ViewTimeline exists. When a card is removed, cancel its animation. Remove with no cards must do nothing and raise no error.IntermediateD05Reveal once, and never hide for goodThe features are hidden in plain CSS (opacity: 0), so a failed script leaves them invisible, and reduced motion hides them too. Rewrite the effect as in the Volt build: hide only under html.reveal-ready, which the script adds; reveal each feature once with an IntersectionObserver (add is-visible when it is in view or above the box, then stop observing it); with reduced motion do not add reveal-ready at all.Advanced