30% offEnding soon
usePrefersReducedMotionLoading saved progress…

usePrefersReducedMotion

Reduced motion is an accessibility preference that asks interfaces to reduce or replace non-essential animation. CSS reads it with @media (prefers-reduced-motion: reduce); JavaScript receives the same signal from window.matchMedia. Build a React hook that reports the preference now and stays current if it changes while the component is mounted.

Signature

function usePrefersReducedMotion(defaultValue?: boolean): boolean;

defaultValue defaults to false. Return it safely when window or window.matchMedia is unavailable. After mount in a supporting browser, the media query's matches value is authoritative.

Examples

function AnimatedNotice() {
  const reduceMotion = usePrefersReducedMotion();

  return <aside className={reduceMotion ? 'no-motion' : 'slide-in'}>Saved</aside>;
}
// The browser reports that reduced motion is enabled at mount.
renderHook(() => usePrefersReducedMotion()).result.current; // true

// A later change event reports matches: false.
// The same mounted hook now returns false.

Notes

  • Use the exact query (prefers-reduced-motion: reduce). Read matches after mount and subscribe to the returned MediaQueryList object's change event.
  • Let the browser win after mount. Its current matches value replaces defaultValue, even when they disagree.
  • Remove the exact listener. Cleanup must pass the same handler reference to removeEventListener on the same query object.
  • Stay environment-safe. Do not read window during render; unsupported and server environments keep defaultValue without throwing.
  • Only report the preference. Changing classes, persisting an override, and choosing which animations to remove are out of scope.