Motion
Motion communicates relationships and reinforces hierarchy. Use the right token for the right moment — fast for press states, slow for reveals — and combine duration with easing to shape how an element arrives or departs.
Duration
Five steps, each tuned to a specific interaction type. Heavier geometry and content reveals warrant longer durations; micro-interactions should be nearly invisible.
| Token | Value | Preview | Use |
|---|---|---|---|
--duration-fast | 80ms | Press / active states | |
--duration-base | 120ms | Standard hover interactions | |
--duration-slow | 200ms | Fill, colour, and indicator transitions | |
--duration-enter | 250ms | Enter / exit geometry — drawers, panels | |
--duration-reveal | 400ms | Content reveal and stagger animations |
Usage rules
- fast — press and active states only. The user should feel the response, not watch it.
- base — the default for hover colour and background shifts.
- slow — fill and progress indicators; anything tracking a measured change.
- enter — panel slide-ins, drawer opens, nav transitions. The default for geometry.
- reveal — content that appears in stages (hero lines, staggered cards). Use sparingly.
Easing
All three easings are one-directional — they describe how something arrives, not how it oscillates. The preview below shows each curve in the direction it is designed to be used.
| Token | Value | Preview | Use |
|---|---|---|---|
--ease-default | ease | General transitions with no strong directional intent | |
--ease-out | ease-out | Elements entering the screen — decelerate into position | |
--ease-spring | cubic-bezier(0.16, 1, 0.3, 1) | Expressive, high-attention moments — drawers, modals, reveals |
Usage rules
- ease-default — safe choice when direction is neutral (colour shifts, opacity fades).
- ease-out — anything sliding or fading into view; the standard pairing with
--duration-enter. - ease-spring — use for one expressive moment per interaction. Not for loops or repeated micro-interactions.
- prefers-reduced-motion —
base.csssetstransition-durationandanimation-durationto0.01mswhen the user has requested reduced motion; no extra guard is needed if you importfarn.css. In custom animation code, always add an explicit@media (prefers-reduced-motion: reduce)guard.
Pairing guide
| Situation | Duration | Easing |
|---|---|---|
| Button press / active | --duration-fast | --ease-default |
| Hover colour shift | --duration-base | --ease-out |
| Panel / drawer enter | --duration-enter | --ease-spring |
| Panel / drawer exit | --duration-enter | --ease-out |
| Content reveal | --duration-reveal | --ease-out |
Code example
.panel {
transform: translateY(8px);
opacity: 0;
transition:
transform var(--duration-enter) var(--ease-spring),
opacity var(--duration-enter) var(--ease-out);
}
.panel.is-open {
transform: translateY(0);
opacity: 1;
}