CSS Motion Systems
Production-oriented motion guidance for web UI. Focused on interaction clarity, performance, and accessibility -- not decorative animation.
When to Use
- Building or refining interaction motion in product UI
- Choosing between CSS transition, keyframes, WAAPI, and View Transitions API
- Creating route transitions or shared element transitions
- Defining motion tokens (duration, distance, easing) for a design system
- Reviewing motion quality, performance, and accessibility
When NOT to Use
- Static content with no interaction or state change
- Cases where motion increases cognitive load without adding clarity
- Immediate state updates where any delay harms usability
Motion Goals
Each motion proposal should satisfy at least one:
- Continuity -- where things came from and where they go
- Feedback -- action acknowledged with clear response
- Hierarchy -- what changed most and why
- Focus guidance -- attention moves to the right target
Mechanism Selection
Choose the lightest mechanism that satisfies the interaction:
- CSS transition -- state changes on a single element (hover, open/close, selected)
- CSS keyframes -- multi-stage timeline or repeated motion (loading, pulse, choreography)
- WAAPI -- imperative sequencing, playback control, cancel/reverse sync with logic
- View Transitions API -- continuity across DOM swaps, route changes, or layout mode changes
Transform Strategy
Individual properties (translate: / rotate: / scale:)
Prefer when:
- You want composable state layers (base styles + state overrides)
- Different interactions control different transform channels
- You need clearer design-token mapping
transform: shorthand
Use when:
- Transform order is intentionally coupled
- You combine multiple functions and must preserve exact sequence
- You need functions not exposed as individual props
translate3d() and 3D transforms
Use only when:
- You need actual 3D/perspective behaviour
- You have profiled a measurable compositor benefit in a real bottleneck
Avoid translate3d() as a blanket "GPU hack" -- it increases layer memory and can cause jank.
Easing
- Use
cubic-bezier() for most product interactions.
- Use
linear() for piecewise velocity control and custom motion signatures.
- Tokenise easing values and reuse consistently.
See: references/LINEAR_EASING_PATTERNS.md
View Transitions API
Same-document transitions
- Wrap DOM/state update in
document.startViewTransition(() => update())
- Name only meaningful shared elements with
view-transition-name
- Style transition pseudo-elements intentionally
Cross-document transitions
- Opt in with
@view-transition { navigation: auto; }
- Keep shared element naming consistent across pages
- Ensure entry/exit states remain meaningful when transition is unavailable
Key pseudo-elements
::view-transition-old(root) / ::view-transition-new(root)
::view-transition-old(name) / ::view-transition-new(name)
::view-transition-group(name)
Failure and fallback
- Feature-detect and fall back to standard state updates
- Respect reduced motion by removing spatial travel and keeping clear state change
- Never block core interactions while waiting for transition effects
See: references/VIEW_TRANSITION_RECIPES.md
Timing Heuristics
- Micro interactions:
120-180ms
- Component transitions:
180-260ms
- Structural/layout/route transitions:
240-420ms
- Exits generally faster than enters
Starter Tokens
See: references/MOTION_TOKENS.css
Performance Rules
- Prefer animating
transform and opacity
- Avoid animating layout-affecting props (
top, left, width, height) for frequent interactions
- Minimise long-running infinite animations on large surfaces
- Use
will-change sparingly and remove when not needed
- Profile before and after changes (frame stability, long tasks, layer count)
Accessibility Rules
- Support
@media (prefers-reduced-motion: reduce)
- Replace large travel/zoom with fade or instant state change under reduced motion
- Keep feedback timing responsive; avoid long delays before state confirmation
- Ensure focus order, visibility, and keyboard behaviour remain correct during/after transitions
Review Checklist
Interaction quality
- Motion explains a state change, not just decoration
- Direction and distance match spatial context
- Enter and exit timing feels intentional and asymmetrical
- Staggering used only when it improves hierarchy
Performance
- Primary animated properties are
transform and/or opacity
- No avoidable layout-thrashing animations in frequent interactions
- Layer promotion controlled, not over-applied
- Interaction remains responsive under realistic load
Accessibility
prefers-reduced-motion: reduce implemented
- Reduced-motion behaviour keeps state changes understandable
- Focus management correct through transitions
- Keyboard and assistive tech flows not blocked by animation
View Transitions
- Feature detection and graceful fallback present
- Shared element naming scoped and meaningful
- Pseudo-element styles explicit for root and shared groups
- Cross-document behaviour verified on supported browsers
Validation
- Tested on desktop and mobile viewport sizes
- Tested in at least one lower-power or throttled scenario
- No visual tearing, clipping, or timing drift in rapid interactions
1---2name: css-motion-systems3description: CSS motion design and implementation for web interfaces. Use when designing or building transitions, animations, `linear()` easing, transform strategy, View Transitions API patterns, motion tokens, or reviewing motion quality and accessibility.4license: UNLICENSED5---67# CSS Motion Systems89Production-oriented motion guidance for web UI. Focused on interaction clarity, performance, and accessibility -- not decorative animation.1011## When to Use1213- Building or refining interaction motion in product UI14- Choosing between CSS transition, keyframes, WAAPI, and View Transitions API15- Creating route transitions or shared element transitions16- Defining motion tokens (duration, distance, easing) for a design system17- Reviewing motion quality, performance, and accessibility1819## When NOT to Use2021- Static content with no interaction or state change22- Cases where motion increases cognitive load without adding clarity23- Immediate state updates where any delay harms usability2425## Motion Goals2627Each motion proposal should satisfy at least one:28291. **Continuity** -- where things came from and where they go302. **Feedback** -- action acknowledged with clear response313. **Hierarchy** -- what changed most and why324. **Focus guidance** -- attention moves to the right target3334## Mechanism Selection3536Choose the lightest mechanism that satisfies the interaction:3738- **CSS transition** -- state changes on a single element (hover, open/close, selected)39- **CSS keyframes** -- multi-stage timeline or repeated motion (loading, pulse, choreography)40- **WAAPI** -- imperative sequencing, playback control, cancel/reverse sync with logic41- **View Transitions API** -- continuity across DOM swaps, route changes, or layout mode changes4243## Transform Strategy4445### Individual properties (`translate:` / `rotate:` / `scale:`)4647Prefer when:4849- You want composable state layers (base styles + state overrides)50- Different interactions control different transform channels51- You need clearer design-token mapping5253### `transform:` shorthand5455Use when:5657- Transform order is intentionally coupled58- You combine multiple functions and must preserve exact sequence59- You need functions not exposed as individual props6061### `translate3d()` and 3D transforms6263Use only when:6465- You need actual 3D/perspective behaviour66- You have profiled a measurable compositor benefit in a real bottleneck6768Avoid `translate3d()` as a blanket "GPU hack" -- it increases layer memory and can cause jank.6970## Easing7172- Use `cubic-bezier()` for most product interactions.73- Use `linear()` for piecewise velocity control and custom motion signatures.74- Tokenise easing values and reuse consistently.7576See: [references/LINEAR_EASING_PATTERNS.md](references/LINEAR_EASING_PATTERNS.md)7778## View Transitions API7980### Same-document transitions8182- Wrap DOM/state update in `document.startViewTransition(() => update())`83- Name only meaningful shared elements with `view-transition-name`84- Style transition pseudo-elements intentionally8586### Cross-document transitions8788- Opt in with `@view-transition { navigation: auto; }`89- Keep shared element naming consistent across pages90- Ensure entry/exit states remain meaningful when transition is unavailable9192### Key pseudo-elements9394- `::view-transition-old(root)` / `::view-transition-new(root)`95- `::view-transition-old(name)` / `::view-transition-new(name)`96- `::view-transition-group(name)`9798### Failure and fallback99100- Feature-detect and fall back to standard state updates101- Respect reduced motion by removing spatial travel and keeping clear state change102- Never block core interactions while waiting for transition effects103104See: [references/VIEW_TRANSITION_RECIPES.md](references/VIEW_TRANSITION_RECIPES.md)105106## Timing Heuristics107108- Micro interactions: `120-180ms`109- Component transitions: `180-260ms`110- Structural/layout/route transitions: `240-420ms`111- Exits generally faster than enters112113## Starter Tokens114115See: [references/MOTION_TOKENS.css](references/MOTION_TOKENS.css)116117## Performance Rules118119- Prefer animating `transform` and `opacity`120- Avoid animating layout-affecting props (`top`, `left`, `width`, `height`) for frequent interactions121- Minimise long-running infinite animations on large surfaces122- Use `will-change` sparingly and remove when not needed123- Profile before and after changes (frame stability, long tasks, layer count)124125## Accessibility Rules126127- Support `@media (prefers-reduced-motion: reduce)`128- Replace large travel/zoom with fade or instant state change under reduced motion129- Keep feedback timing responsive; avoid long delays before state confirmation130- Ensure focus order, visibility, and keyboard behaviour remain correct during/after transitions131132## Review Checklist133134### Interaction quality135136- Motion explains a state change, not just decoration137- Direction and distance match spatial context138- Enter and exit timing feels intentional and asymmetrical139- Staggering used only when it improves hierarchy140141### Performance142143- Primary animated properties are `transform` and/or `opacity`144- No avoidable layout-thrashing animations in frequent interactions145- Layer promotion controlled, not over-applied146- Interaction remains responsive under realistic load147148### Accessibility149150- `prefers-reduced-motion: reduce` implemented151- Reduced-motion behaviour keeps state changes understandable152- Focus management correct through transitions153- Keyboard and assistive tech flows not blocked by animation154155### View Transitions156157- Feature detection and graceful fallback present158- Shared element naming scoped and meaningful159- Pseudo-element styles explicit for root and shared groups160- Cross-document behaviour verified on supported browsers161162### Validation163164- Tested on desktop and mobile viewport sizes165- Tested in at least one lower-power or throttled scenario166- No visual tearing, clipping, or timing drift in rapid interactions