What Is the Core Idea Behind Scroll Animation?
A scroll animation website maps scroll position to animation time. The page measures how far the visitor has scrolled through a section, converts that to a number between 0 and 1, and uses it as the animation's playhead. Scroll forward and the sequence plays; scroll back and it reverses exactly.
Strip away the polish and every scroll-animation site does this same thing. The visitor is not watching an animation; they are holding the scrubber. Everything else in this note, the implementations, the libraries, the performance rules, is in service of that one mapping.
This is why good scroll sites feel calm and bad ones feel jumpy. If the animation is driven by anything other than that progress number, easing timers, scroll-event bursts, one-way triggers, it drifts out of sync with the visitor's hand. Bind everything to progress and the page becomes deterministic: same scroll position, same frame, forwards or backwards.
How Do You Implement the Scroll Playhead?
Three implementations cover nearly every scroll animation site: scrubbing a pre-rendered video's current time, drawing exported image frames to a canvas, and driving live DOM or WebGL elements with GSAP ScrollTrigger. The right choice depends on what is being animated: offline-rendered footage, exported stills, or real elements on the page.
Once scroll progress exists as a clean 0-to-1 signal, something has to consume it. Each of the three approaches below trades visual ceiling against asset weight and flexibility, and most flagship pages end up using one as the spine and another for accents.
Video Scrubbing
Render the sequence as a video, then map scroll progress to the video's current time. This is what our own homepage does: a pre-rendered sequence scrubbed by scroll, so a cinematic shot plays exactly as fast as the visitor moves. The strength is visual quality, since anything you can render offline can ship. The catch is encoding: the video needs a keyframe interval short enough for smooth backwards seeking, which is something default encoder settings never give you.
Frame Sequences on Canvas
Export the animation as hundreds of still images, preload them, and draw the right frame to a canvas based on progress. Seeking is instant in both directions, which is why the most famous product-story sites use it. The cost is asset weight and memory: hundreds of images need careful sizing, modern formats, and progressive loading, or the experience pays for its smoothness up front with a long wait.
GSAP ScrollTrigger
For animating real elements, DOM, SVG, or a live 3D scene, GSAP's ScrollTrigger with scrub enabled maps a whole animation timeline onto a scroll range. The docs describe scrub exactly the way this note does: it links the animation's progress directly to the scrollbar, so it acts like a scrubber. Pinning holds a section fixed while the timeline plays through it. This is the workhorse on most of our builds because it composes: one scrubbed timeline can move text, swap images, and drive a WebGL camera together, which is exactly how the scroll-driven heroes in our Three.js for business sites note are wired.
Why Do Scroll Animation Sites Use Smooth-Scroll Libraries?
Native scrolling moves in discrete steps, especially on a mouse wheel, and each step lands as a visible jump in a scrubbed animation. Smooth-scroll libraries interpolate scroll position into a continuous signal while keeping the native scrollbar and accessibility behavior intact, so scrubbed motion reads as fluid instead of stuttering.
Libraries like Lenis do exactly this interpolation, and the animation reads scroll through the library instead of raw events, so the result stops feeling like a slideshow. One discipline applies: there is exactly one source of scroll truth, and every animation reads from it. Two systems fighting over scroll position is the classic broken-parallax bug.

What Are the Performance Rules?
Animate only transform and opacity, render in a requestAnimationFrame loop instead of raw scroll handlers, preload assets before revealing the experience, budget on a mid-range phone, and keep pinned sections short. Scroll animation runs during the most latency-sensitive interaction on the web, so every dropped frame is felt immediately.
The visitor's hand is on the wheel the whole time. The first rule below is the one Google's animation guidance states outright: avoid any property that triggers layout or paint, and keep animations on the compositor. The rules we hold on every build:
- Animate only transform and opacity. Properties like width, top, or margin force layout recalculation on every frame; transforms run on the compositor.
- Never animate inside a raw scroll event handler. Read scroll position and render in a requestAnimationFrame loop, so work happens at most once per frame.
- Gate the experience on preloading. A scrubbed sequence that is still loading frames stutters in the visitor's hand. Show a loading state, then reveal when assets are genuinely ready.
- Budget on a mid-range phone. Scroll performance on a developer's desktop proves nothing; the failure mode lives on a three-year-old Android over cellular.
- Keep pinned sections honest. Every pin extends the page; too many and visitors feel trapped scrolling through a presentation they cannot skip.
When the scrubbed element is a canvas, two more numbers matter: cap the device pixel ratio at 2, because rendering beyond that burns frame budget for sharpness nobody can see, and size the canvas to its displayed dimensions rather than the full viewport when the animation only occupies a band of the page. These are the same mobile budgets we hold in our React Three Fiber in production work. Most scroll jank we are asked to diagnose traces back to one of the items on this list, and the fix is usually a one-day change rather than a rebuild.
None of this is just feel. Scroll-heavy pages get scored on the same field metrics as every other page, the same numbers our SEO content systems are built to protect: a hero that ships megabytes of frames late drags Largest Contentful Paint past budget, a saturated main thread pushes interaction latency past the INP line, and frames that shove the layout around register as layout shift. The thresholds, measured at the 75th percentile of real visits, come from Google's Core Web Vitals:
| Core Web Vital | What it measures | Good threshold |
|---|---|---|
| Largest Contentful Paint (LCP) | Loading | 2.5 seconds or less |
| Interaction to Next Paint (INP) | Interactivity | 200 milliseconds or less |
| Cumulative Layout Shift (CLS) | Visual stability | 0.1 or less |
How Do You Respect Reduced Motion?
Operating systems expose a prefers-reduced-motion preference for visitors who get motion sickness from large moving elements. A responsible scroll site detects it, keeps the content and layout, and replaces scrubbed motion with static frames or simple fades. The page should read as a well-designed document with the cinematography off.
The preference is prefers-reduced-motion, which MDN documents alongside the reason it exists: scaling and panning large objects are vestibular motion triggers. A scroll site that ignores it is broken for those visitors in a way no performance work fixes. The story should survive with the motion turned off.
When Is Scroll Animation the Right Call?
Scroll animation earns its cost when there is a real sequence to tell: a product that assembles, a process with stages, a brand moment that benefits from pacing. It is the wrong tool for content-dense pages where visitors want to scan and leave, so reserve it for flagship pages.
We reach for it on flagship pages and keep the rest of the site fast and conventional, which is the balance we strike across our 3D website design work and our broader website builds. The same discipline applies underneath: a scrubbed hero only pays off if the page beneath it still loads fast and reads clearly.



