Motion
Motion explains change; it never performs. The entire vocabulary is a fade plus a rise of at most 12px, timed on a five-step scale, and product UI never exceeds 240ms.
Durations
Five steps cover every timing decision. Feedback stays nearly instant, and anything longer than 240ms belongs to marketing surfaces, never the product.
| Token | Value | Use |
|---|---|---|
duration.xs | 80ms | Hover and pressed feedback |
duration.sm | 160ms | Exits, overlays, selection controls, small state changes |
duration.md | 240ms | Entrances, disclosure, page and step changes |
duration.lg | 480ms | Page-level reveals, marketing only |
duration.xl | 720ms | Rare marketing sequences |
480ms and 720ms exist for marketing reveals. Inside the product every interaction animation completes within 240ms; only waiting indicators, skeleton pulses and the feedback run, breathe on lg because they describe time passing.
opacity 0 → 1 · ease-out
bars drawn at 0.5px per ms
Easing
Two curves do all the work: ease-out settles everything entering, in-out serves movement that returns to rest on screen. Linear exists only for progress indicators.
ease.out
cubic-bezier(0.16, 1, 0.3, 1)
The default curve for everything entering. Every recipe on this page uses it.
ease.in-out
cubic-bezier(0.65, 0, 0.35, 1)
Move and return: an element that travels and settles back within the same view.
ease.linear
linear
Waiting indicators only: spinners, progress bars, and skeleton pulses, the permitted loops.
ease.standard is an alias of ease.out kept for compatibility; new work names ease.out directly.
Recipes
Ten named recipes cover the product. Each demo runs the exact tokens; stages rest in their final state and replay on request.
| Recipe | Movement | Timing | Use |
|---|---|---|---|
hover | Color and border; press sinks 1px | xs · ease.out | Hover and pressed feedback on controls |
check | Glyph draw-in | sm · ease.out | Checkbox mark drawing in when selected |
radio | Dot fade and settle | sm · ease.out | Radio dot appearing as the fill settles |
switch | Thumb translate | sm · ease.out | Thumb crossing its 16px track |
enter | Fade + 8px rise | md · ease.out | Cards, panels, and step content entering |
exit | Fade only | sm · ease.out | Anything leaving; exits never translate |
overlay | Fade + 4px rise | sm · ease.out | Menus, popovers, and toasts |
page | Fade + 8px rise | md · ease.out | Route-level entrance; enter at page scale |
stagger | 60ms steps | 6 items maximum | List entrances; later items land together |
sticky-raise | Shadow fade | sm | None to raised as content passes beneath |
The product implements these with Motion for React; the library contract lives on UI frameworks. The sticky-raise shadow change is drawn on elevation and shadow, and the selection recipes carry the exact values the controls page documents.
color and border · 80ms ease-out
press · sinks 1px
every interactive element answers with color or border; nothing lifts or scales beyond the press
draw-in · dot fade · thumb translate · 160ms ease-out
live controls: toggle them; the mark lands and stops, with no bounce
Where could a reader first lose the thread of this paragraph?
fade + 8px rise · 240ms ease-out
Your draft is saved
fade only · 160ms ease-out
never translates; the demo resets after the fade
fade + 4px rise · 160ms ease-out
shadow.overlay
enter per item · 60ms steps
6 items maximum; later items land together
Limits
Fade plus a translate of at most 12px is the entire vocabulary. If an effect needs more than opacity and a short straight move, it does not belong in Inline.
A quiet enter. The card fades in, rises 8px from the dashed start, and stops dead at rest; replay it to watch.
A bouncy entrance. Springs, scale, and overshoot perform for attention; drawn here as a frame, never implemented.
Off the table entirely: scale, bounce, springs, parallax, typewriter reveals, confetti, and perpetual ambient loops. The 12px cap governs elements entering the view; a selection control moves exactly as far as its anatomy defines, so the switch thumb crosses its 16px track on sm and stops without bounce.
Spinners and progress bars are the only elements that may repeat, and they run on linear time. Nothing else in Inline moves perpetually; the one looping demo on this page is the waiting bar under rule 6.
Reduced motion
When a person asks for less motion, movement is removed entirely, not shortened. Opacity fades either complete within sm or apply instantly.
| Recipe | Default | Under reduced motion |
|---|---|---|
hover | Color and border, 80ms; press sinks 1px | Color and border unchanged; the press translate is removed |
check, radio, switch | Draw, fade, and slide, 160ms | The new state applies instantly; fill and position still carry it |
enter and page | Fade + 8px rise, 240ms | Fade only within sm, or instant |
exit | Fade, 160ms | Fade within sm, or instant |
overlay | Fade + 4px rise, 160ms | Fade only within sm, or instant |
stagger | 60ms steps | Delays removed; every item lands at once |
sticky-raise | Shadow fade, 160ms | Final shadow appears immediately |
Because nothing may encode meaning in motion alone, removing movement costs nothing: every state a transition explains is also carried by color, text, or position in the resting frame. This page obeys the same contract; with reduced motion on, each demo shows its final frame the moment Replay is pressed, and the waiting bar under rule 6 holds still.
Rules
Eight limits keep motion explanatory, and each one runs its own demonstration. When a case is unclear, the quieter option wins.
-
Start from stillness. Nothing moves until an interaction or a state change gives motion one job to do.
replay is the interaction: one enter, then still againat rest · no idle motion
-
Fade first, then rise. Opacity carries every transition; translation adds at most 12px, and exits never translate.
8px rise · in bounds32px rise · past the 12px cap
Your draft is saved
exit · fade only, never translates -
Product UI stops at md. Every product animation completes within 240ms; lg and xl belong to marketing surfaces.
the scale to scale: the highlight ends at the 240ms cap
-
Enter on ease-out, return on in-out. Reserve linear for spinners and progress bars.
schematic travel on a track; linear stays reserved for rule 6enter · ease-out, lands and staysmove and return · in-out, 240ms each way
-
Never scale, spring, or bounce. An element stops exactly at its resting point, without overshoot.
the card lands exactly on the line and never crosses itthe dashed line is rest
-
Loop only while waiting. Spinners and progress bars are the only perpetual motion, on linear time.
waiting · linear · may repeatthe one legal loop on this page; it stops under reduced motion
-
Stagger six at most. Steps run 60ms apart and later items land together.
six steps, 60ms apart; a seventh item would land with the sixth
-
Remove movement under reduced motion. Fades complete within sm or apply instantly, and no meaning rides on motion alone.
default · fade + 8px risewith the OS preference on, both settle to the final frame at oncereduced · fade only, within sm