Recipe

Recipe: prefers-reduced-motion design

Ship motion-rich interfaces that instantly respect the user's system-level accessibility preference.

The media query

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

One block kills every animation and transition site-wide. No JavaScript required.

Tailwind variant

<div className="motion-safe:animate-fade-in">
  Animated only when safe
</div>

<div className="motion-reduce:animate-none motion-reduce:transition-none">
  Static when reduced
</div>

Tailwind ships motion-safe and motion-reduce variants out of the box. No config needed.

JavaScript guard

const prefersReduced = window.matchMedia(
  '(prefers-reduced-motion: reduce)'
).matches;

if (!prefersReduced) {
  initScrollParallax();
  initPageTransitions();
}

Gate expensive animation init behind the matchMedia check. Listen for changes with .addEventListener('change').

Testing checklist

  • Toggle the OS setting and reload — zero motion must play.
  • Verify no layout shift when animations are stripped.
  • Ensure carousels and autoplay still function without motion.
  • Test with screen readers; reduced motion often pairs with a11y tools.

Meridian tip: Combine this recipe with the color-contrast recipe for a complete accessibility baseline that ships in under 2 KB of CSS.