# Honor prefers-reduced-motion

**MUST** · **ID:** `animations-prefers-reduced-motion` · **Category:** animations
**Source:** [Vercel](https://github.com/vercel-labs/agent-skills/blob/main/skills/web-design-guidelines/SKILL.md)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/animations-prefers-reduced-motion

> MUST: Honor `prefers-reduced-motion` (provide reduced variant); in Tailwind use the `motion-safe:`/`motion-reduce:` variants

Provide a reduced-motion variant for all animations

Some users experience motion sickness or vestibular symptoms from movement they did not initiate. The media query surfaces an OS-level preference they have already expressed, so honouring it costs one @media block. The load-bearing detail: "reduced" is not "none". Strip the spatial travel and the spring, but KEEP the opacity crossfades and the instant state changes, so the interface still says what happened — a state change that was only ever communicated by motion becomes invisible the moment the motion is dropped (animations-lottie-never-opacity-only is the corollary). ibelick's baseline-ui converges on the same rule from the agent-guidelines side ("SHOULD respect `prefers-reduced-motion`"), which is why this corpus states it once here rather than twice. CAVEAT, and it is worth stating plainly: Raphael Salaja's sounds-on-the-web skill advises treating prefers-reduced-motion as a proxy for sound sensitivity — defaulting audio OFF when it is set. That is pragmatic, because no `prefers-reduced-sound` media query has ever shipped, and it is a defensible default. But it is lossy: a vestibular preference is not a sound preference, and the overlap is a guess, not a signal. Use it as a default-OFF heuristic, never as a substitute for an explicit, persisted sound toggle (see interactions-sound-is-user-owned).

## Bad — do not do this

`animations-prefers-reduced-motion-bad`

```tsx
import { ReducedMotionSwitch } from '@/components/demo-kit/ReducedMotionSwitch';

export function PrefersReducedMotionBad() {
  return (
    <div className="space-y-4">
      <ReducedMotionSwitch />
      <div className="h-16 flex items-center rounded-lg bg-muted/50 px-3 overflow-hidden">
        <div
          className="size-8 rounded-md bg-primary"
          style={{ animation: 'rmSlide 1.2s ease-in-out infinite alternate' }}
        />
      </div>
      <style>{`@keyframes rmSlide { from { transform: translateX(0); } to { transform: translateX(180px); } }`}</style>
      <p className="text-xs text-destructive">
        The animation runs regardless of the preference — toggling "reduce motion" changes nothing, so sensitive users get no relief
      </p>
    </div>
  );
}
```

## Good — do this

`animations-prefers-reduced-motion-good`

```tsx
import { ReducedMotionSwitch } from '@/components/demo-kit/ReducedMotionSwitch';
import { useSimulatedReducedMotion } from '@/hooks/useSimulatedReducedMotion';

export function PrefersReducedMotionGood() {
  const reduced = useSimulatedReducedMotion();

  return (
    <div className="space-y-4">
      <ReducedMotionSwitch />
      <div className="h-16 flex items-center rounded-lg bg-muted/50 px-3 overflow-hidden">
        <div
          className="size-8 rounded-md bg-primary"
          style={{
            animation: reduced ? 'none' : 'rmSlide 1.2s ease-in-out infinite alternate',
            transform: reduced ? 'translateX(86px)' : undefined,
          }}
        />
      </div>
      <style>{`@keyframes rmSlide { from { transform: translateX(0); } to { transform: translateX(180px); } }`}</style>
      <p className="text-xs text-success">
        Toggle "reduce motion" on and the movement stops — the box simply rests. The content stays, just calm
      </p>
    </div>
  );
}
```

## References

- [prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-reduced-motion)
- [ibelick — baseline-ui SKILL.md](https://github.com/ibelick/ui-skills/blob/main/skills/baseline-ui/SKILL.md)
- [Raphael Salaja — sounds-on-the-web SKILL.md](https://raw.githubusercontent.com/raphaelsalaja/skill/main/skills/sounds-on-the-web/SKILL.md)
- [Accessible Animations](https://www.a11yproject.com/posts/understanding-vestibular-disorders/)
