SKP
Get in touch

JOURNAL 01

SCROLL-DRIVEN ANIMATION.

Why trigger-based scroll animation accumulates bugs, and why treating scroll position as a pure input fixes an entire class of them at once.

Entry
01
Subject
Scroll choreography
Length
Short
Code
Conceptual
Two cyan particle waves interleaving across black, scroll position mapped directly to animation progress
Concept render — position mapped to progress

//The bug everyone ships#

The common pattern: watch for an element entering the viewport, fire an animation. It works in testing and fails in the wild. Scroll fast and the trigger fires while the previous animation is still running. Scroll up and back down and it fires again, or doesn't. Reload halfway down the page and half your elements are in their initial state because their triggers never fired. Every one of these is the same bug: the animation holds state that the scroll position can contradict.

//The reframe#

Stop thinking about events and think about a function. Scroll position is an input; every animated property is an output computed from it. Given a progress value between zero and one, where should this element be, what's its opacity, how blurred is it? Compute that from scratch on every frame and never store it. Now there's no state to desynchronise — a reload, a scrollbar drag, a jump to an anchor, all produce a correct frame because the position fully determines the appearance.

Practically: one requestAnimationFrame loop for the whole page. Read scroll position and any element rectangles you need first, then write all transforms. Reading after writing forces the browser to recompute layout mid-frame, repeatedly, and it's the usual explanation for scroll animation that stutters despite looking cheap.

//The cost#

You compute more than strictly necessary, recalculating values that haven't changed. In exchange you delete an entire category of bug. On every project where I've measured it, the recomputation was nowhere near the bottleneck — layout thrash and paint were, and this approach makes both easier to control.

The same frame discipline applies elsewhere: render budgets as a design material covers the measurement side, and motion timing covers the easing.

Fig. 30 — scroll, raf, layout thrash