Chapter 09 · Motion language
Counterpoint.
Every other piece in this portfolio animates itself. This one is about what happens between the animations: the sentence a page speaks while it changes its mind. A transition is not an effect laid over two states. It is the argument that connects them.
There are eleven of them here. Each one names the job it is doing, each one can be interrupted without the picture jumping, and the count is checked by a harness rather than promised by a caption.
Continuity The masthead enters as a thought, not a cut. The three lines of the opening paragraph rise in the order a reader reads them, so the page has already made an argument about sequence before it has made one about type.
A transition is a sentence, so it has to be parseable
It has a subject, a verb and a consequence. A reader who cannot say what it said has been shown a trick — and a page full of tricks has no voice, only vocabulary. So this chapter holds itself to a short list of what a transition may be for, and files every one of them underneath it.
Hierarchy
This outranks thatOne element is more important than another and the move between them is the argument. Used when scale, weight or position has to change in the reader's head.
State
This has changedThe thing you were looking at is in a different condition: data arrived, a control was committed, a path was chosen. The move tells you that it changed, not where it went.
Continuity
Same thought, further alongTwo states are two distances from one object rather than two different objects. Nothing is unloaded, so the eye never has to re-acquire anything — this is the reason the page exists.
Delight
You did not have to be shown thisThe only intent allowed to be unnecessary. It earns its place by being the shortest thing on the page and by pointing at something true — the one place here where the motion explains the motion.
Hierarchy Section ordinals and rules draw in as each section is reached. The same system on all six heads: it tells you where you are in the argument before you read a word of it.
State The rail on the right edge marks the reading position and is driven by a spring, not a jump — so a fast scroll reads as the pointer being dragged, not as a progress bar being reset.
Delight The pink line under the stage sweeps when a transition commits. It is the shortest motion in the chapter and the only one that exists to point at itself.
Two states are distances from one object, not two objects
The stage is one arrangement with three conditions, not three screens. Stacked, the nine cells gather into three shelves — two, four, three — stepped across the frame, each strip cut to its own width. Opened, they fan out into an uneven spread — deliberately uneven, because a symmetric grid reads as a diagram and a diagram is not a sentence. Pushed once more, the centre cell is promoted and the other eight recede.
Nothing was ever unloaded. There is no moment where a new element arrives and the old one leaves, so the eye is never asked to re-acquire a thing it was already holding. That is the whole claim of continuity, written as geometry rather than as a feeling.
The stage position and the condition on screen. Paste one back to return to this exact pose.
Continuity Stacked → open: the same nine cells, unfolded. Each cell travels along its own path out of the stack, so the stack reads as the same material in a different arrangement. The cyan cursor rides the rail underneath to keep the two readings of "where am I" in agreement.
Hierarchy Open → promoted: one cell outranks the other eight. The eight recede in opacity and pull away from the centre rather than shrinking, which keeps the composition's outer edges where they were. Nothing crosses anything on the way in.
A commit on the stage draws this line, 520ms, once.
A transition you cannot interrupt is a video
Input is continuous and people change their minds while the page is still deciding. So every move on this page is driven by a spring that keeps its velocity: when the target changes mid-flight, the motion continues from exactly where it is, at exactly the speed it had, and turns around. There is no point at which it re-reads a starting position, because there is no starting position to re-read.
Throw sends the stage to the far end and reverses it once it has covered forty percent of the distance. Reverse does the same thing on your timing, and it works while the page is already reversing — which is the case that usually falls apart.
idle · no flight yet — press Throw to run one, and watch the two figures below
Continuity The reversal keeps the velocity it inherited. The two frame figures in the line above are read from the promoted cell's laid-out position, sampled once per animation frame — the same value the compositor receives. They are a report, not a target: a frame that teleports shows up as a spike, which is why the larger of the two should be a fraction of a pixel rather than a multiple.
Use the platform where it is the right tool, and say which one you are in
Some transitions should not be hand-written. When the document is genuinely replaced — a different set of rows, a different condition — the browser already knows how to match the old to the new, and the View Transitions API does in one call what a hand-rolled FLIP does in thirty. Where the movement is a gesture rather than a correspondence, this page does not use it, because a platform API animating something you wanted to author is worse than no platform API at all.
The panel swaps its contents. The readout says which path actually ran, measured from your browser rather than assumed on your behalf. The second button runs the other path on purpose, so both are visible in the same session.
- What this browser exposes
- measuring…
- What ran last
- nothing yet
State The panel swap on the platform path. The browser owns the matching: it captures the old frame, runs your callback, and animates the difference. Used here because the rows really are replaced rather than rearranged.
State The same swap, hand-written, for browsers that have no such thing. Old positions are measured, the content is replaced, and everything that moved is tweened back from where it was — the rows, and the key bar, which changes width on every hop. A row joins condition B and leaves it again, so the correspondence has something to correspond about. Same change, same intent, thirty more lines, no dependency.
Reduced motion is a different composition that happens to hold still
It is not this page with the animation taken out. Every transition here is a change of state with an interpolation drawn between the two states, and the interpolation is the part that goes. The state change does not. The stage still unfolds — instantly. The panel still swaps. The reading indicator still moves. Nothing on this page is reachable only through its movement, so nothing is lost when the movement is refused.
The button below previews that branch in a browser whose system setting you have not changed. Turn it on, then run the stage, the swap and the throw: all three still change state. They simply arrive without interpolating, and the text is identical.
Claim, and how to check it. This chapter says it supports prefers-reduced-motion. The harness proves the claim by emulating the media feature, sampling the stage every animation frame through a transition, and requiring two things at once: that no frame moves, and that the final state still differs from the first. A branch that stops the motion and the effect would pass a weaker test than this one.
State Switching motion branch is itself a state transition, so it says so. The chip and the button read from the same two signals — the media query and the preview attribute — that the engine reads, which is why the label cannot drift away from the behaviour.
The ledger, and the rule it enforces
This is the whole motion system on one table. If a transition were added that could not be filed under one of the four intents, it would not be a transition; it would be vocabulary — and vocabulary without grammar is the thing this chapter exists to argue against.
| System | Intent | What it does | Fires on |
|---|---|---|---|
| masthead | Continuity | Opening lines rise in reading order | load |
| heads | Hierarchy | Section ordinals and rules draw in | scroll into view |
| rail | State | Reading position marker travels | scroll |
| stage | Continuity | Nine cells unfold from a closed stack | Open further |
| promote | Hierarchy | One cell is promoted, eight recede | Open further |
| interrupt | Continuity | Mid-flight reversal keeps velocity | Throw · Reverse now |
| trace | Delight | Correspondence line sweeps on commit | any stage commit |
| platform | State | Panel swap via the platform path | Swap — detected path |
| fallback | State | Panel swap, hand-written | Swap — the other path |
| reduce | State | Motion branch switches, and says so | Preview reduced motion |
| ledger | Hierarchy | The intent index folds away and returns | Show the intent index |
| Intent | Systems | What they have in common |
|---|---|---|
| Hierarchy | heads · promote · ledger | Each one changes what outranks what, and the move is the argument. |
| State | rail · platform · fallback · reduce | Each one says a thing has changed, and refuses to pretend it went somewhere. |
| Continuity | masthead · stage · interrupt | Each one is the same object at a different distance, never a replacement. |
| Delight | trace | One, and it is the shortest thing here. That is the budget. |
Hierarchy The intent index is folded away until it is asked for. The table above answers what each transition is; this one answers which intent it serves, and it is the second question rather than a repeat of the first. One of the two is subordinate, and the transition says so by arriving.