The switch is a signal, not a sentence
prefers-reduced-motion: reduce is one of the few accessibility signals a browser sends unprompted — it means the person at the other end has told their operating system that motion makes them uncomfortable or unwell. Treating it as a binary that blanks all animation is like responding to a wheelchair user by removing the stairs *and* the building. The goal is the same journey, with a different movement system.
The reduced experience should still communicate state, still guide attention, still reward progress — just without vestibular triggers: no large movement, no parallax, no persistent drifting, no simulated motion sickness.
- Keep opacity fades (200–300ms) — fading does not trigger vestibular responses and still carries state changes.
- Replace parallax with stillness plus a subtle shadow or gradient change; the depth cue survives without the motion.
- Replace autoplaying carousels with manual controls that are more visible, not less — the reduced experience gives the user control.
- Replace long springs and overshoot with short settles — the information lands either way.
- Replace scroll-linked reveals with content that is simply visible — a reader with motion sensitivity should not have to scroll-trigger every paragraph into existence.
The second-design principle
The professional framing is to design the reduced experience as a *second design*, not a deletion pass. Ask: what is this animation's job? If the job is 'show the user the item was added', then the reduced version needs a different mechanism for that same job — a color change, a checkmark, a position shift. If the job is pure atmosphere, cut it — but say so in the code, so the next designer knows the cut was a decision.
Motif's motion-spec prompt bakes this in: every specified animation ships with its reduced branch in the same spec — what plays (nothing that moves layout), what fades (opacity only), and the exact media query hook. The reduced experience is in the contract, not bolted on after the audit.
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .01ms !important;
animation-iteration-count: 1 !important;
transition-duration: .01ms !important;
scroll-behavior: auto !important;
}
/* then re-enable the deliberate fades: */
.toast { transition: opacity 250ms ease; }
.progress-bar { transition: width 200ms ease; }
}