How to Respect Reduced Motion in React Animations

Respect reduced motion in React animations with the prefers-reduced-motion media query and Motion's useReducedMotion hook.

6 min read

Respecting reduced motion in React means reading the user's operating system preference and dialing your animations back when they ask. The preference arrives through the prefers-reduced-motion media feature, and you can honor it in both CSS and JavaScript.

The prefers-reduced-motion media query

Users enable reduced motion in their operating system settings, and the browser exposes that choice to CSS. The query below matches when the setting is on.

csscss
.animate-in {
  animation: slide-up 0.3s ease-out;
}
 
@media (prefers-reduced-motion: reduce) {
  .animate-in {
    animation: none;
  }
}

When the preference is active, the slide-up animation is dropped entirely and the element simply appears. The media query is the CSS half of the solution and needs no JavaScript.

Apply it to CSS animations first

Any CSS transition or keyframe animation that moves, scales, or pans should live behind the query. Fades and opacity changes are usually safe, while transforms that move large regions are the main offenders.

The rule of thumb is to reduce non-essential motion, not necessarily all motion. A hover color change can stay, while a card that slides across the screen should become a simple swap. Grouping the overrides in one media query keeps the reduced version easy to review and leaves the animated version untouched.

Detect the preference in JavaScript

When Motion drives the animation, the useReducedMotion hook reports the preference as a boolean. Skip the transform states when it returns true.

App.jsxApp.jsx
import { motion, useReducedMotion } from "motion/react";
 
function Banner({ children }) {
  const reduce = useReducedMotion();
 
  return (
    <motion.div
      initial={reduce ? false : { opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
    >
      {children}
    </motion.div>
  );
}

For reduced motion users the banner skips the slide and only fades in, which keeps the entrance visible without the movement. The full setup for this library is in how to animate React components with Motion.

Avoid the biggest triggers

Scaling, parallax, auto scrolling, and infinite looping movement are the most common vestibular triggers. Replace them with a static or faded equivalent when the preference is active.

Reduce, then remove

Reduced motion does not always mean no motion. Essential feedback, such as a brief fade to confirm a save, can usually stay, while decorative transforms should go. When in doubt, remove the motion that moves large regions and keep the motion that communicates state, because a fade is less likely to trigger vestibular discomfort than a slide or a scale.

Test with the setting enabled on your own machine. macOS and Windows both expose it in their accessibility settings, and toggling it while the app runs shows exactly what a reduced motion user experiences.

The same breakpoint thinking used for layout applies here: treat the preference as another constraint on the design. Responsive React components shows how to structure those checks cleanly.

Rune AI

Rune AI

Key Insights

  • Wrap CSS animations in prefers-reduced-motion: reduce.
  • Read the preference in JavaScript with matchMedia or useReducedMotion.
  • Skip transform animations when the user requests reduced motion.
  • Keep essential feedback, remove scaling and panning.
  • Treat reduced motion as a requirement, not an afterthought.
RunePowered by Rune AI

Frequently Asked Questions

Should I remove all motion for reduced motion users?

Not necessarily. Reduce non-essential motion such as parallax, scaling, and panning. Essential feedback such as a fade can often stay, or run with a shorter duration.

How do I read the preference in JavaScript?

Use window.matchMedia with the prefers-reduced-motion query, or call the useReducedMotion hook from the Motion library, which wraps that check for you.

Is prefers-reduced-motion widely supported?

Yes. It is a Baseline widely available feature, supported in Chrome 74, Firefox 63, Safari 10.1, and their mobile equivalents.

Conclusion

Respecting reduced motion in React means checking the prefers-reduced-motion preference and dialing animations back. Use the CSS media query for styles, the useReducedMotion hook for JavaScript driven animation, and keep essential feedback while removing vestibular triggers.