# How to Handle prefers-reduced-motion for Accessibility in Animations

> Learn to handle prefers-reduced-motion for accessibility by disabling animation effects. Preserve essential feedback for a better user experience.

- Repository: [Emil Kowalski/skills](https://github.com/emilkowalski/skills)
- Tags: best-practices
- Published: 2026-08-01

---

**Wrap transform-based animations in `@media (prefers-reduced-motion: reduce)` blocks to disable motion-heavy effects while preserving essential opacity and color feedback that communicates state changes.**

The `emilkowalski/skills` repository establishes clear standards for respecting user motion preferences in modern web interfaces. According to the animation guidelines documented across several skill files, implementing **prefers-reduced-motion** is not about eliminating all visual feedback but about replacing movement-heavy effects with safer alternatives that prevent vestibular discomfort.

## Core Principles from the Repository

The following architectural principles emerge from [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md), [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md), and [`skills/prototype/PICKER.md`](https://github.com/emilkowalski/skills/blob/main/skills/prototype/PICKER.md).

### Never Eliminate Feedback

Users still require visual cues for state changes such as button activation or selection. As noted in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md) at line 62, you should preserve **opacity or color changes** while removing only the movement-heavy transforms. Eliminating all feedback creates accessibility barriers for users who rely on visual confirmation of interactions.

### Prefer Opacity and Color Over Transform

According to [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md) at line 200, swap slides, springs, and parallax effects for short **opacity cross-fades**. Color changes that aid comprehension should be retained, as these properties are less likely to cause vestibular issues compared to spatial movement.

### Gracefully Disable Heavy Motion

The [`skills/prototype/PICKER.md`](https://github.com/emilkowalski/skills/blob/main/skills/prototype/PICKER.md) file at line 70 demonstrates wrapping **transform-based transitions** inside `@media (prefers-reduced-motion: reduce)` blocks and setting them to `none`. This ensures the user’s system-level Reduced Motion preference is respected without requiring JavaScript detection.

### Gate Hover and Gesture Animations

Touch devices fire false hover events, and reduced-motion users may have hover disabled. Combine **prefers-reduced-motion** with `@media (hover: hover) and (pointer: fine)` to conditionally enable hover effects only on devices that properly support them.

### Maintain Consistent Timing

A sudden removal of motion should not alter perceived responsiveness. Keep animation durations short (≤ 200 ms) and use identical easing curves for both reduced-motion and normal paths to ensure the interface feels equally responsive regardless of user settings.

## Implementation Examples

### CSS-Only Reduction

As implemented in [`skills/prototype/PICKER.md`](https://github.com/emilkowalski/skills/blob/main/skills/prototype/PICKER.md), wrap transform overrides in a media query while preserving color transitions:

```css
/* Normal animation */
.button {
  transition: background-color 150ms ease, transform 250ms var(--ease-out);
  transform: translateY(0);
}

/* Reduced‑motion override */
@media (prefers-reduced-motion: reduce) {
  .button {
    transition: background-color 150ms ease; /* keep color fade */
    transform: none;                         /* drop movement */
  }
}

```

### React Hook with useReducedMotion

The **Apple Design** skill recommends using Framer Motion’s `useReducedMotion` hook to programmatically adapt animations:

```tsx
import { useReducedMotion } from 'framer-motion';

function FancyCard() {
  const shouldReduce = useReducedMotion(); // respects the media query
  const animation = shouldReduce
    ? { opacity: 1, transform: 'none' }          // cross‑fade only
    : { opacity: 1, transform: 'translateY(0)' }; // normal slide‑in

  return (
    <motion.div
      initial={{ opacity: 0, transform: 'translateY(20px)' }}
      animate={animation}
      transition={{ duration: 0.2, ease: 'easeOut' }}
      className="card"
    />
  );
}

```

### Guarding Hover Effects on Touch Devices

Following the accessibility recommendations in [`skills/review-animations/STANDARDS.md`](https://github.com/emilkowalski/skills/blob/main/skills/review-animations/STANDARDS.md), combine pointer and motion queries:

```css
/* Enable hover scaling only on devices that support hover */
@media (hover: hover) and (pointer: fine) {
  .icon:hover {
    transform: scale(1.08);
    transition: transform 120ms ease-out;
  }
}

/* Ensure reduced‑motion users never get the scale */
@media (prefers-reduced-motion: reduce) {
  .icon:hover {
    transform: none;
  }
}

```

## Summary

- Wrap **transform transitions** in `@media (prefers-reduced-motion: reduce)` blocks to disable movement while keeping the interface responsive.
- Replace motion-heavy effects with **opacity fades** or **color shifts** to maintain essential visual feedback.
- Use the **`useReducedMotion`** hook in React components to adapt animations programmatically.
- Gate hover effects using `@media (hover: hover) and (pointer: fine)` to prevent false triggers on touch devices.
- Test computed styles in browser DevTools with "Reduced motion" enabled to verify only intended properties change.

## Frequently Asked Questions

### What is the prefers-reduced-motion media query?

The **`prefers-reduced-motion`** media query detects whether a user has requested that the system minimize non-essential motion. It returns `reduce` when the user has enabled the Reduced Motion accessibility setting, or `no-preference` when they have not.

### Should I remove all animations for users who prefer reduced motion?

No, you should **never eliminate feedback entirely**. Remove only transform-based movements like slides, scales, and rotations. Preserve opacity fades and color changes that communicate state changes, as these provide necessary visual cues without causing vestibular discomfort.

### How do I detect reduced motion preferences in JavaScript?

Use **`window.matchMedia('(prefers-reduced-motion: reduce)')`** to check the preference in vanilla JavaScript, or use the **`useReducedMotion`** hook from Framer Motion in React applications. Both methods respect the system-level setting and update dynamically if the user changes their preferences.

### How can I test reduced motion settings during development?

Open your browser’s DevTools and enable the **"Reduced motion"** emulation in the rendering or accessibility panel. Inspect computed styles to verify that transform properties are disabled while opacity and color transitions remain active, ensuring your implementation matches the standards defined in `emilkowalski/skills`.