Pattern 05 — progress & orientation UI

Notes on motion in interfaces

This page is the demo. As you read: the bar along the top measures your position in the document, the table of contents tracks whichever section sits at reading height, and after 600 pixels a button offers the way back. Three small mechanisms, three short scripts — all annotated at the bottom of the source. The essay they decorate is about the discipline they exemplify.

Why motion matters

Interfaces are explanations. Every screen makes claims about what exists, what changed and what is about to happen — and motion is the only channel that can express change itself rather than mere states. A panel that slides in from the right tells you where it lives and how to send it home. A number that counts up tells you it grew rather than being replaced. Remove the motion and the information survives, but the reader is left doing the diffing by hand.

That framing keeps a designer honest. Motion that explains a change earns its frames; motion that merely advertises the designer's toolbox is asking the user to pay attention-tax on every visit. The progress bar above is a useful baseline: it moves constantly, yet nobody would call this page animated. It is pure feedback, spent exactly where feedback is due.

Timing and duration

Interface motion lives in a narrow band. Under about 100 milliseconds a transition reads as instantaneous; past 400 the interface starts to feel like it is performing for you; most micro-interactions belong between 150 and 300. Scale shifts the band — a full-screen sheet can afford 350ms where a checkbox cannot — but the ceiling is real, and it is lower than most first drafts.

A transition is a promise about causality: the shorter the promise, the more often you can afford to make it.

Scroll-driven effects, like the ones across this repo, obey a different clock: the user's own hand. That is their superpower — pace belongs to the reader — and their trap, because a reader who scrolls fast compresses your carefully planned choreography into a single frame. Design every scroll effect to be skimmed past without loss.

Easing is a voice

Two animations with identical durations can feel like different products. Linear easing is mechanical — right for progress meters, wrong for nearly everything else. Ease-out curves, fast then settling, make interfaces feel responsive: the element leaps to answer and lands softly. Ease-in belongs almost exclusively to exits, letting departing elements gather speed like something released from your attention.

The reveals in this repo use cubic-bezier(.22, 1, .36, 1) — a hard deceleration with a whisper of overshoot absorbed before it lands. Pick one or two such curves and repeat them everywhere: consistency of easing does more for perceived quality than any individual flourish.

Choreography

When several things move at once, their relationships carry the meaning. Siblings stagger; a parent leads its children; unrelated elements never share a cue. The 60–90ms sibling offset used in the reveals page is small enough to feel like one gesture, large enough to imply order. Beyond four or five participants, choreography collapses into weather — group them and move the group.

Order is information, too. Revealing a list top-to-bottom confirms reading order; revealing it edge-in suggests symmetry; revealing it randomly suggests a bug. If you cannot say what a sequence claims about the content, the sequence is not finished.

The performance budget

Animation quality is mostly the absence of interruption, and interruptions come from work scheduled where work does not fit. The rules that keep 60 frames per second are unglamorous: animate only transform and opacity; let IntersectionObserver watch geometry instead of polling it; batch every read and write through requestAnimationFrame; mark scroll listeners passive so the browser never waits for you before moving the page.

The scripts on this page follow one more rule worth stealing: write only on change. The TOC observer fires a handful of times per screenful, not per pixel; the back-to-top toggle flips a class at one threshold. Between those moments, scrolling this page costs almost nothing beyond the bar's single transform — which is why it stays smooth on hardware you have never tested.

Restraint and preference

Some readers find interface motion delightful; for others — vestibular disorders, migraines, plain taste — it ranges from tiring to disabling. prefers-reduced-motion is the contract between the two groups, and honouring it is not a feature, it is table stakes. On this page the preference switches anchor scrolling to instant, materialises the back-to-top button without travel, and leaves the progress bar alone, because position feedback that moves only with the reader's own gesture is information, not decoration.

The deeper habit: design the still version first. If the page is complete, legible and pleasant with every animation deleted, motion becomes what it should have been all along — a generosity, offered to those who want it, invisible to those who do not.