Scroll-triggered animation as the missing piece for scrollytelling on the web
Dan PetersonSynopsis — AI-drafted from Dan's notes
A tutorial essay on utilitybend, Brecht De Ruyte’s blog, published 13 October 2026. The argument
is that the web already had scroll-driven animation, where the scroll position scrubs an
animation back and forth, and that this is the wrong tool for most storytelling. A headline or a
card entering the viewport shouldn’t freeze half-drawn when the reader stops scrolling. What was
missing was a native way to let the scroll position start an ordinary timed animation and then
let it run. Until now that meant JavaScript, with an IntersectionObserver toggling a class.
The new CSS does it with two properties. timeline-trigger goes on the watched element and names
a trigger with a view() source and an activation range (his default is entry 100% exit 0%).
animation-trigger then ties an animation to that trigger with an enter action and an exit
action: play-forwards, play-backwards, play-once, pause, reset or none. Reversible
sections pair forwards with backwards; one-time intros use play-once none. A trick with
attr() lets one rule serve every trigger name. Five demos build it up: a masked headline reveal
staggered with sibling-index(), cascading feature cards, variable-font letters, a kinetic quote
that mixes triggered reveals with a scroll-driven background drift, and a carousel that draws SVG
paths as cards slide in sideways, all without JavaScript.
The last third is responsibility. Split-letter headings need an aria-label on the heading and
aria-hidden on the spans; prefers-reduced-motion should switch the triggers off; and because
support is Chromium-only so far, everything sits behind @supports (animation-trigger: none) with
the content visible by default, so a browser without the feature just shows the page.