Every fancy interaction pattern comes with a hidden tax: the visitor has to learn it. Drag to rotate, hold to explore, press keys to move. Each one filters out the people who did not read the instructions. Scroll is the exception. Every person who has ever used the internet arrives already fluent, and that is why the best 3D storytelling on the web is scroll-driven: it is cinema where the audience holds the camera dolly.
Why scroll works on the brain
Scroll gives the visitor control over time. A video plays at its own pace and asks for patience. A scroll-driven sequence moves exactly as fast as curiosity does, backward as easily as forward, and that control changes how people engage. They lean in instead of waiting. The story becomes something they are doing rather than something happening at them.
There is a quieter benefit too: scroll produces honest analytics. Depth reached, time per section, where people reverse to reread, every one of these is a signal about the story itself. When a majority reverses at the same section, that section is either the most interesting thing on the page or the most confusing, and the surrounding behavior tells you which.
It also lets you borrow a century of film grammar. Dolly in for intimacy, pull wide for scale, cut on motion, hold on stillness. I used exactly this in Void Atlas, where camera choreography walks the viewer through deep-space distances that raw numbers cannot communicate. The scroll bar became the timeline of a documentary. How motion timing carries meaning is its own subject, and I wrote about it in The Semiotics of Digital Space.
The architecture underneath
Strip away the tools and every scroll-driven scene is the same machine: scroll position becomes a normalized progress value between zero and one, and that value drives everything. Camera position along a path, material opacity, text reveals, particle states. The scene is a function of progress. Nothing animates on its own clock, everything reads from the same timeline.
// the whole genre in six lines
const progress = clamp(scrollY / (docHeight - viewportHeight), 0, 1);
camera.position.copy(cameraPath.getPointAt(progress));
camera.lookAt(target.getPointAt(progress));
material.opacity = smoothstep(0.3, 0.45, progress);
titleReveal.set(smoothstep(0.5, 0.6, progress));
Everything else is elaboration on those six lines. Sections map to progress ranges, easing curves shape how fast meaning arrives inside each range, and the smoothing layer decides how the raw scroll value becomes the calm interpolated one the scene actually reads.
Resist the urge to let anything own its own timeline. The moment one element animates on a clock while everything else reads from scroll, the scene develops two kinds of time, and visitors feel the seam even when they cannot point at it. Ambient motion can breathe on its own, background particles, idle shimmer. Anything narrative belongs to the scroll.
The important decision is keeping that machine honest: read the scroll once per frame, drive the scene inside the render loop, and never let animation work trigger browser layout. Transforms and shader uniforms are cheap. Anything that makes the browser recalculate the page mid-scroll turns a sixty-frames-per-second story into a slideshow, especially on the phones I wrote about in the performance post.
The toolkit
- GSAP ScrollTrigger is the industry standard for a reason. The scrub option maps timelines to scroll position with one line, pinning and snapping included. If you use one tool from this list, use this one.
- Lenis replaces native scrolling with a smoothed, interpolated version, which is what makes 3D scenes feel attached to the page instead of jittering behind it. Most award-level scroll sites you have admired are running it.
- Theatre.js gives you a real animation editor in the browser: keyframe the camera, scrub the sequence, hand the timeline to scroll. For long cinematic sequences it beats hand-typed keyframes by a full order of magnitude.
- For flat sections between 3D moments, plain CSS scroll-driven animations now cover more than most people think, at zero JavaScript cost.
Pinning, ranges, and the shape of a section
The architecture gets more interesting the moment a section needs to hold still. Pinning, freezing a section on screen while scroll keeps driving its internal animation, is the strongest tool in the genre and the easiest to overuse. A pinned section is a promise to the visitor: this is worth stopping for. Break that promise twice and they stop believing the page.
I budget pins the way an editor budgets slow motion. One, maybe two per page, at the moments that carry the actual argument, and never longer than the content inside them justifies. Everything else stays free scrolling, because the contrast is what makes the pinned moments land. A page that is all emphasis has none.
Ranges deserve equal care at their boundaries. Animations that fire the instant a section enters the viewport feel jumpy, so I give each range a small entry buffer, and I make sure every animation resolves to a stable state before its section leaves. The visitor who scrolls fast should land on composed frames, never mid-tween.
The craft rules
Tools make scroll-driven work possible. Restraint makes it good. The failure mode of this genre is the site that fights its visitor: hijacked scroll speed, sections that trap the wheel, motion that keeps going long after the finger stopped. The visitor holds the camera. The moment the site wrestles them for it, trust is gone and so are they.
- Respect momentum. Smooth the scroll, never redirect it. If the visitor flicks, the page goes where they sent it.
- Give length cues. People tolerate long sequences when they can feel their position in them. A quiet progress indication beats a surprise every time.
- Keep text still while it is being read. Motion behind text is cinematic. Motion of text is hostile.
- Honor prefers-reduced-motion with a real alternative, not an empty page. Some visitors need the story without the ride.
- Test on touch. Mobile scroll has its own physics, plus the address bar resize that has broken more scroll scenes than any browser bug.
The mobile reality
Touch scrolling has physics of its own: flick velocities are higher, direction changes are constant, and the finger covers part of the screen while it drives. Choreography tuned on a trackpad usually runs too slow on touch, so mobile deserves its own timing pass rather than a scale factor.
Then there is the viewport itself. Mobile browsers resize the window as the address bar collapses, which silently changes every measurement your ranges depend on. Modern viewport units help, but the real insurance is remeasuring on resize and never trusting a cached viewport height. This one issue has broken more scroll scenes than every browser bug combined, mine included.
Structure the story before the scene
The most common mistake in this genre is not technical. It is writing the choreography before the story. Decide first what the visitor should understand at each stage of the page, in plain sentences. Then assign each sentence a progress range, and only then decide what the camera does to serve it. Scenes built the other way around, motion first and meaning retrofitted, always read as demos, and visitors can smell a demo in the first two hundred pixels of scrolling.
Write the story in words before opening the editor, too. Scroll choreography is expensive to restructure once built, so the cheap iterations happen in an outline: what appears, what it means, what the visitor should feel at each stage. The outline is the screenplay. The scene is just production.
Where to start
Start smaller than you think. One scene, one camera move, one idea revealed on the way down. A single dolly-in that lands exactly when the headline arrives will outperform six minutes of choreography that exhausts its audience by the second act. Film editors learned this a hundred years ago: the cut you notice is the cut that failed.
Then build the machine properly: progress value, one timeline, scene as a function of scroll. Add Lenis when the native scroll feels detached, ScrollTrigger when the choreography grows, Theatre.js when hand-tuned keyframes stop scaling. And keep the visitor in charge of the camera the whole way through. You are not animating a page. You are directing a shot that someone else gets to hold, and that someone decides how your story ends.