Nobody is filming your page.
There is no camera, so every camera move on the web had to be invented. Dolly invents 34 of them in CSS, and scrolling back up rewinds them.
Fourteen kilobytes, watching a scrollbar.
AOS ships 14 kB of JavaScript to notice where you are. Dolly ships a stylesheet, and a stylesheet cannot fail to boot.
kB
D O L L Y
It is named after a cart. A dolly carries a camera through a shot and never appears in one. Sibling to Foley, which does the sound.
You already know these words.
Cinema named these moves before the web existed. Knowing what they do is most of the documentation.
Every film ever made is a flipbook.
This one is thirty-six pictures on a single sheet. Scrolling picks which one you see — no canvas, no decode loop, nothing running. The browser is moving a background by one cell.
What it refuses to do.
"tilt-up"It never hides your content.
AOS, ScrollReveal and sal all put opacity: 0 in a base rule and reveal it from script. Block the script and the page is blank. Dolly puts the hidden state only in @keyframes, so no support means it didn't animate, never it didn't appear. The worst it can do is nothing.
Nothing runs, so nothing runs late.
No IntersectionObserver, no scroll listener, no rAF loop, no init call, no provider, no hydration. There is no boot sequence to wait on and no script tag to block — including for the pinned chapters you just scrolled through.
Reduced motion means off, not slower.
Under prefers-reduced-motion every move switches off, scenes stop pinning, and the page renders exactly as authored — because the authored state was never the hidden one.
Firefox is fine, today.
Scroll timelines run in Chrome 115+, Edge, Safari 26+ and Opera — about 87% of the web, with Firefox landing in 159. The other 13% get a complete, still page, which is the design, not the degradation. There is no shim to ship.
The full set.
the reference| Move | What it does |
|---|---|
| fade | opacity only |
| tilt-up | rises into place |
| tilt-down | drops into place |
| pan-left | slides in from the right |
| pan-right | slides in from the left |
| dolly-in | camera pushes toward it |
| dolly-out | camera pulls back from it |
| crane | lifts and settles |
| rack | focus pulls from blurred |
| whip | fast pan with motion blur |
| reveal | wipes in horizontally |
| wipe-up | wipes in vertically |
| roll | rotates level |
| progress | tracks the whole page |
| travel | rides page scroll |
| parallax | drifts against the scroll |
| zoom | slow continuous push |
| drop | falls through the frame |
| pass | tracks past, reversing its yaw |
| push | the camera travels toward it |
| pull | the camera draws back |
| swing | rotates in on Y |
| tumble | pitches in on X |
| fly | travels from far, past the camera |
| beat | arrives, holds, leaves |
| beat-in | defocuses in, holds, defocuses out |
| hold | arrives and stays |
| iris | an aperture opening |
| track | vertical scroll, horizontal travel |
| draw | a stroke drawing itself; needs pathLength="1" |
| count | a number counting up, printed by counter() |
| sequence | a sprite strip, stepped one frame per slice of scroll |
| mask | footage inside letterforms |
| letter | tracking closes as it arrives |
There is no step two.
one attribute, plus scenesLink the stylesheet, then annotate markup you already have. No init call, no wrapper component, no configuration object, because nothing is running that could read one.
<link rel="stylesheet" href="dolly.css">
<h1 data-dolly="tilt-up">Arrives as you reach it</h1>
<img data-dolly="rack" src="still.jpg" alt="">
<!-- a pinned scene: the chapters above are all this -->
<div data-dolly-scene>
<div data-dolly-pin>
<img data-dolly="zoom" data-dolly-on="scene" src="shot.jpg" alt="">
</div>
</div>
/* one caveat: a parent with overflow:hidden becomes its own scroll
container and pins the move at its end state. Use overflow:clip. */
npm i @dollyjs/core
that is the whole library
34 moves · 0 kB of JavaScript · one attributeDolly is named for the camera dolly, the cart that carries a camera through a shot. The name came first and stands on its own. It is also, this year, a word that is hard to write down without thinking of someone else. Dolly Parton's Imagination Library has sent a book to a child every month since 1995, and still sends them. It takes donations. This library does not.
1946–2026