Principles
Motion confirms, it never performs. Every animation answers a user action or marks a state change. Nothing moves to be noticed.
Calm is a speed. Fast enough to feel responsive, slow enough to never startle. Nothing bounces, nothing overshoots, nothing loops for attention.
One thing moves at a time. Simultaneous animations compete; sequenced ones read as intention.
Easing
Two curves cover the system. Run them and feel the difference.
cubic-bezier(0.2, 0.8, 0.2, 1)Default for UI transitions: hovers, reveals, toggles.
--ease-standard is the default for hovers, toggles, and state changes. --ease-out-quart starts fast and settles long, which makes it right for entrances and scroll reveals: content arrives, then rests.
Never use ease-in alone for anything user-facing, and never use linear except for continuous motion like marquees.
Duration
| Token | Value | Use |
|---|---|---|
--duration-fast |
150ms | Hovers, small state changes |
--duration-base |
300ms | Reveals, toggles, most transitions |
--duration-slow |
600ms | Section entrances, large surface moves |
--duration-ambient |
8000ms | Background drift, barely perceptible |
If a transition needs a value between these, pick the shorter one.
Scroll reveals
Content fades up 18px on --ease-out-quart over --duration-slow, staggered by document order. Elements reveal once and stay; scrolling back up does not replay them.
Reduced motion
prefers-reduced-motion: reduce is honored everywhere: reveals render in place, transitions collapse to instant, and ambient drift stops. This is not optional and ships in the base stylesheet.