Motion
Durations and easings for every transition, so the whole product moves at one pace.
Try it
Pick a duration, a curve and a property. Changing any control replays the move.
150ms · --ease-out--duration-normal
transform
Duration
Ease
Property
Delay
.marker {
transition: transform var(--duration-normal) var(--ease-out);
}--duration-slower before the move starts.Durations
Seven steps, from 50 to 500ms. Most of the product moves at 100 or 150ms.
--duration-instant50ms
--duration-fast100ms
--duration-normal150ms
--duration-moderate200ms
--duration-slow300ms
--duration-slower400ms
--duration-slowest500ms
--ease-in-out, so only the duration differs.1150ms · easeOutCubicThe gauge the product ships.
500ms · --ease-outThe ceiling, on the same arc.
Easings
Six curves. Press Replay to run a dot along each one.
Duration
Slowed down so each curve’s shape shows.linear
in
out
in-out
spring
bounce
Composed transitions
Four tokens are whole transition values, each on --duration-normal.
Loops every 2s, slowed to 450ms.
--transition-transformtransform only
--transition-allevery property, layout included
/* Same duration. Only one of them moves the rest of the row. */
.save { transition: var(--transition-transform); }
.save--lazy { transition: var(--transition-all); }
/* --transition-all: all var(--duration-normal) var(--ease-in-out)
and `all` includes width, padding and radius — every property
that forces the elements beside it to be laid out again. */--transition-all animates width too, so the buttons beside it move. --transition-transform leaves them still.Usage
- Use
--duration-normal(150ms) for most transitions, and--duration-fast(100ms) for hover colour changes. - Keep anything a person acts on at 200ms or less. Use 400ms and 500ms only for skeletons and page transitions.
- Use
--ease-outfor things entering, and--ease-in-outfor everything else. - Use a composed token instead of listing properties, so every component animates the same ones.
- Keep
--ease-bouncefor a button’s success and error pops. - Don’t use
--transition-all. It animates layout, so the things around it move. - With reduced motion on, skip the move and show the end state.
Tokens
| Token | Value | Where it lands |
|---|---|---|
| --duration-instant | 50ms | — |
| --duration-fast | 100ms | Hover colour and background changes. |
| --duration-normal | 150ms | The default. Most component transitions. |
| --duration-moderate | 200ms | Disclosures and dropdowns opening. |
| --duration-slow | 300ms | — |
| --duration-slower | 400ms | Skeletons and page transitions. |
| --duration-slowest | 500ms | Skeletons and page transitions. |
| --ease-linear | linear | — |
| --ease-in | cubic-bezier(.4,0,1,1) | — |
| --ease-out | cubic-bezier(0,0,.2,1) | Anything entering. |
| --ease-in-out | cubic-bezier(.4,0,.2,1) | The default curve. |
| --ease-spring | cubic-bezier(.34,1.56,.64,1) | Not in use. |
| --ease-bounce | cubic-bezier(.68,-.55,.265,1.55) | Button success and error pops. |
| --transition-colors | color, background, border · 150ms | Text, fill and border colour. |
| --transition-opacity | opacity · 150ms | Opacity only. |
| --transition-transform | transform · 150ms · ease-out | Transform only. The one on ease-out. |
| --transition-all | all · 150ms | Every property, layout included. Avoid. |
| (no token) | 1150ms · easeOutCubic | Gauge sweep. |
| (no token) | 1800ms | Compass needle settling onto its bearing. |