← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

prefers-reduced-motion — Accessible Animations

accessibility Beginner

Also Known As

prefers-reduced-motion reduce motion vestibular accessibility motion sensitivity

TL;DR

A CSS media query and JavaScript API that detects when a user has requested reduced motion in their OS settings, allowing you to disable or simplify animations that can trigger vestibular disorders.

Explanation

Motion on screen — parallax, auto-playing animations, rapid transitions — can trigger dizziness, nausea, and migraines in users with vestibular disorders (affecting up to 35% of adults over 40). The `prefers-reduced-motion: reduce` media query fires when the user enables 'Reduce Motion' in macOS/iOS, Windows 'Show animations', or Android accessibility settings. The correct approach is to retain meaningful transitions (opacity fades, simple slides) but remove spinning, bouncing, zooming, and parallax effects. JavaScript can read the preference via `window.matchMedia('(prefers-reduced-motion: reduce)')`. WCAG 2.1 Success Criterion 2.3.3 (Animation from Interactions) at AAA level requires an option to disable motion; at AA level, WCAG 2.3.1 restricts content that flashes more than 3 times per second.

Common Misconception

Reduced motion means removing all animations — users requesting reduced motion still benefit from subtle transitions like simple fades and colour changes that communicate state. The goal is removing vestibular-triggering motion (spinning, bouncing, zooming, parallax), not all visual feedback.

Why It Matters

Ignoring motion preferences can make your site physically uncomfortable or unusable for users with vestibular disorders, migraines, or epilepsy. It is also increasingly a WCAG compliance requirement and covered by accessibility laws in many jurisdictions.

Common Mistakes

  • Setting `animation: none` globally under `prefers-reduced-motion` — removes useful feedback like loading spinners and state transitions.
  • Only disabling CSS animations but not JavaScript-driven animations (GSAP, Framer Motion, custom `requestAnimationFrame` loops).
  • Not pausing auto-playing carousels and video backgrounds — these are often more problematic than CSS animations.
  • Testing only in a browser without actually enabling the OS-level reduced motion setting — the media query won't fire in browser devtools alone on some platforms.

Code Examples

💡 Note
Replacing the spin animation with a fade-pulse keeps the loader meaningful without triggering vestibular symptoms.
✗ Vulnerable
/* No motion consideration — spins indefinitely */
.loader {
    animation: spin 1s linear infinite;
}
.hero {
    animation: parallax-float 4s ease-in-out infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes parallax-float { 50% { transform: translateY(-20px); } }
✓ Fixed
/* Default: full animation */
.loader {
    animation: spin 1s linear infinite;
}
.hero {
    animation: parallax-float 4s ease-in-out infinite;
}

/* Reduced motion: keep functional feedback, remove vestibular triggers */
@media (prefers-reduced-motion: reduce) {
    .loader {
        animation: fade-pulse 2s ease-in-out infinite; /* subtle opacity, no spin */
    }
    .hero {
        animation: none; /* parallax removed entirely */
    }
    * {
        transition-duration: 0.01ms !important; /* near-instant transitions */
        scroll-behavior: auto !important;
    }
}

@keyframes fade-pulse { 50% { opacity: 0.5; } }

// JavaScript: respond to preference
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)');
if (prefersReduced.matches) pauseCarousel();

Added 24 Mar 2026
Views 24
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 2 pings S 0 pings S 2 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Amazonbot 8 Perplexity 4 Google 3 Unknown AI 2 Ahrefs 2 ChatGPT 1
crawler 20
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Wrap all CSS animations in `@media (prefers-reduced-motion: no-preference)` or add a `@media (prefers-reduced-motion: reduce)` block that disables spinning/bouncing/parallax
📦 Applies To
web
🔗 Prerequisites
🔍 Detection Hints
CSS animation or transition declarations not wrapped in prefers-reduced-motion media query; auto-playing carousels without pause controls
Auto-detectable: ✓ Yes axe lighthouse
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✗ Manual fix Fix: Low Context: File

✓ schema.org compliant