CSS Motion and Accessibility: Using prefers-reduced-motion

CSS motion can make interfaces feel polished and responsive, but it can also be distracting or uncomfortable for some users. This article explains how to respect motion preferences with prefers-reduced-motion, when to reduce animation, and how to design motion that stays accessible.

Quick answer: Use the CSS media query @media (prefers-reduced-motion: reduce) to provide a calmer version of your animations and transitions. Keep the interface usable without motion, and never rely on animation for essential information.

Difficulty: Beginner

You'll understand this better if you know: basic CSS selectors, how transitions and animations work, and the purpose of media queries.

1. What Is Motion Accessibility?

Motion accessibility means designing animations, transitions, and other moving effects so they do not create barriers for people who are sensitive to motion. The main CSS tool for this is the user preference media query prefers-reduced-motion.

In practice, you do not remove all movement from the web. You provide a reduced-motion alternative that avoids unnecessary movement, large zooming effects, and long animated transitions.

2. Why Motion Accessibility Matters

Some users experience dizziness, nausea, headaches, or concentration issues when interfaces move too much. A parallax effect, scrolling animation, or sudden zoom can be uncomfortable even if the design looks attractive to others.

Supporting reduced motion is important because it:

Motion accessibility matters most when movement is decorative, large-scale, or repeated often. If motion communicates status or helps explain a state change, it should be kept subtle and still remain understandable without animation.

3. Basic Syntax or Core Idea

The core technique is a media query that checks whether the user prefers reduced motion. Inside that query, you can shorten transitions, stop animations, or replace movement-heavy effects with simpler styles.

Minimal pattern

Start with a normal animated style, then override it for users who prefer less motion.

.card {
  transition: transform 250ms ease;
}

.card:hover {
  transform: translateY(-4px);
}

@media (prefers-reduced-motion: reduce) {
  .card {
    transition: none;
  }

  .card:hover {
    transform: none;
  }
}

This pattern keeps the default behavior for most users and provides a motion-light version for users who request it.

4. Step-by-Step Examples

Example 1: Reducing a hover transition

Hover effects often use short transitions. For reduced motion, removing the animated shift can make the interaction feel stable while still keeping the hover state visible through color or outline.

.button {
  background: #2563eb;
  color: #fff;
  transition: transform 180ms ease, background-color 180ms ease;
}

.button:hover {
  transform: translateY(-2px);
  background-color: #1d4ed8;
}

@media (prefers-reduced-motion: reduce) {
  .button {
    transition: background-color 120ms ease;
  }

  .button:hover {
    transform: none;
  }
}

The reduced version keeps the visual state change but removes the movement.

Example 2: Turning off a repeating animation

Infinite or repeated animations are more likely to bother motion-sensitive users. In reduced motion mode, replacing them with a static indicator is usually better than keeping a looped animation.

.loader {
  width: 2rem;
  height: 2rem;
  border: 4px solid #cbd5e1;
  border-top-color: #2563eb;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .loader {
    animation: none;
    border-top-color: #94a3b8;
  }
}

Here the spinning motion disappears, but the loader still has a visible presence.

Example 3: Replacing a slide-in panel

Sliding panels can feel like objects moving across the screen. For reduced motion, it is often better to fade in quickly or show the panel without movement.

.panel {
  opacity: 0;
  transform: translateX(24px);
  transition: opacity 240ms ease, transform 240ms ease;
}

.panel.is-open {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .panel {
    transition: opacity 120ms linear;
    transform: none;
  }
}

The reduced-motion version avoids the sideways movement while still revealing the panel clearly.

Example 4: Respecting animated page sections

Some sites animate content into view. If you use those effects, make sure the content is still fully readable and usable when motion is removed.

.feature {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 300ms ease, transform 300ms ease;
}

.feature.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .feature {
    transition: opacity 150ms ease;
    transform: none;
  }
}

This keeps the content accessible even if the scroll-triggered motion is toned down or removed.

5. Practical Use Cases

Use prefers-reduced-motion when motion is decorative or could be distracting. Common situations include:

It is especially useful in product interfaces, dashboards, e-commerce sites, marketing pages with animated sections, and content-heavy applications where users spend a long time reading.

6. Common Mistakes

Mistake 1: Removing motion entirely for everyone

Some developers disable animation globally because they think accessibility means no motion at all. That can make the site feel less clear for users who benefit from gentle feedback.

Problem: This approach removes all transitions for all users, even when motion is small and helpful.

* {
  animation: none;
  transition: none;
}

Fix: Keep the default motion and override it only inside the reduced-motion media query.

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none;
    transition: none;
  }
}

The corrected version respects the user's preference instead of changing the experience for everyone.

Mistake 2: Hiding important state changes inside animation

Another common issue is using motion to communicate something essential, such as an element appearing, an error arriving, or a status changing. If motion is removed, the state can become unclear.

Problem: The content depends on animation to be noticed, so reduced-motion users may miss the change entirely.

.message {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 300ms ease, transform 300ms ease;
}

.message.is-visible {
  opacity: 1;
  transform: none;
}

Fix: Make the visible state clear even without movement, and use motion only as a enhancement.

.message {
  opacity: 0;
}

.message.is-visible {
  opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
  .message {
    transform: translateY(20px);
    transition: opacity 300ms ease, transform 300ms ease;
  }
}

The fix keeps the state understandable even when animation is reduced.

Mistake 3: Keeping long or repeated animations in reduced mode

Not all motion has the same impact. Long-duration or infinite animations are much more likely to cause discomfort than a brief color transition.

Problem: The animation still runs in reduced motion, so the interface does not actually respect the user's preference.

@media (prefers-reduced-motion: reduce) {
  .banner {
    animation: slideGlow 6s ease-in-out infinite;
  }
}

Fix: Remove the repeated motion or replace it with a static style change.

@media (prefers-reduced-motion: reduce) {
  .banner {
    animation: none;
    box-shadow: none;
  }
}

This version removes the repeated effect and keeps the banner visually stable.

7. Best Practices

Practice 1: Design motion as an enhancement, not a dependency

Motion should make the interface nicer, not necessary for understanding it. Build the layout so the content is clear before animation runs.

.dialog {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: no-preference) {
  .dialog {
    opacity: 0;
    transform: scale(0.98);
    transition: opacity 200ms ease, transform 200ms ease;
  }
}

This approach keeps the base state accessible even when motion is reduced.

Practice 2: Prefer short, subtle motion when it is helpful

Short transitions are usually less likely to be problematic than large movement or repeated loops. Use them for lightweight feedback like color changes or tiny shifts.

.tab {
  transition: color 150ms ease, border-color 150ms ease;
}

Subtle motion is easier to tolerate and more likely to remain usable for a wider range of people.

Practice 3: Remove movement before removing meaning

If you have to simplify an effect, keep the visual information and remove the movement first. A static style change is often enough.

.toast {
  opacity: 0;
}

.toast.is-open {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .toast {
    transition: opacity 120ms ease;
  }
}

This keeps the notification understandable without making it feel jumpy.

8. Limitations and Edge Cases

One practical rule is simple: if the effect makes the page harder to follow, or if it exists mostly for decoration, provide a reduced-motion alternative.

9. Practical Mini Project

Here is a small card component that uses motion for polish, but remains calm when reduced motion is requested. The default version animates slightly on hover; the reduced version removes movement and keeps only a color-based change.

.product-card {
  padding: 1.25rem;
  border: 1px solid #dbe3ea;
  border-radius: 0.75rem;
  background: #fff;
  transition: transform 200ms ease, box-shadow 200ms ease;
}

.product-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
}

@media (prefers-reduced-motion: reduce) {
  .product-card {
    transition: box-shadow 120ms ease;
  }

  .product-card:hover {
    transform: none;
    box-shadow: 0 0 0 2px #2563eb;
  }
}

This example is useful because it keeps the interaction readable, attractive, and motion-aware at the same time.

10. Key Points

11. Practice Exercise

Expected output: A card that feels animated for most users, but remains stable and accessible when reduced motion is requested.

Hint: Use color, border, or shadow changes to preserve feedback after removing transform.

Solution:

.exercise-card {
  padding: 1rem;
  border: 1px solid #cbd5e1;
  border-radius: 0.5rem;
  background: #ffffff;
  transition: transform 180ms ease, border-color 180ms ease;
}

.exercise-card:hover {
  transform: translateY(-3px);
  border-color: #2563eb;
}

@media (prefers-reduced-motion: reduce) {
  .exercise-card {
    transition: border-color 120ms ease;
  }

  .exercise-card:hover {
    transform: none;
    border-color: #2563eb;
  }
}

This solution works because the hover state remains obvious even after the movement is removed.

12. Final Summary

CSS motion accessibility is about making animations and transitions safer and more comfortable without giving up good design. The key tool is prefers-reduced-motion, which lets you detect when a user wants less motion and adjust your styles accordingly.

The best approach is to keep motion optional, subtle, and decorative. Make sure the interface remains understandable without animation, and use static cues such as color, spacing, opacity, and outline to communicate state when motion is reduced.

If you want to go further, review your site's transitions, loading states, and entrance animations one by one and decide which ones can be simplified for reduced-motion users.