// guide

Accessible Motion and Animation: prefers-reduced-motion and WCAG

Animation can delight most users and physically sicken others. This guide covers who motion affects, what WCAG actually requires (pause/stop/hide, no flashing, animation from interactions), and how to honor the prefers-reduced-motion setting in CSS and JavaScript — reducing motion for the people who need it without stripping personality from your interface.

intermediate visual-design

// 01 · who motion affects

Who Motion Affects

Motion on screen is not a neutral aesthetic choice. For people with vestibular disorders — conditions affecting the inner ear and balance — large or unexpected movement can cause real physical symptoms: dizziness, nausea, disorientation, and migraine that can last hours. Parallax scrolling, full-screen zoom transitions, and content that slides or flies across the viewport are common triggers.

Motion also affects people with attention and cognitive differences, for whom animated or auto-updating content is distracting and makes text harder to read, and people prone to photosensitive seizures, for whom flashing content is a genuine hazard. A sizeable share of users deliberately switch on their operating system's "reduce motion" setting — the web's job is to listen for that request and respond to it.

The goal is respect, not sterility Accessible motion does not mean a static, lifeless interface. It means motion is purposeful, calm by default, and reducible for anyone who asks. Most users keep the animation; the people who need less get less.

// 02 · what wcag requires

What WCAG Requires

Three success criteria govern motion. Two are Level A — the baseline every site should meet — and one is AAA but cheap enough that honoring it is standard practice.

Criterion Level What it requires
2.2.2 Pause, Stop, Hide A For motion that starts automatically, lasts more than 5 seconds, and runs beside other content, give users a way to pause, stop, or hide it (e.g. a carousel or auto-scrolling ticker).
2.3.1 Three Flashes or Below Threshold A Nothing may flash more than three times in any one-second period. Flashing above this threshold can trigger seizures.
2.3.3 Animation from Interactions AAA Let users disable non-essential motion triggered by their own actions (scroll, hover, click). Honoring prefers-reduced-motion satisfies this.
Flashing is a safety issue, not a preference 2.3.1 is not about taste — content that flashes more than three times a second can induce seizures in people with photosensitive epilepsy. This one is never optional and is not covered by a reduced-motion setting. Avoid rapid flashing entirely.

// 03 · respecting prefers-reduced-motion in css

Respecting prefers-reduced-motion in CSS

The prefers-reduced-motion media feature exposes the user's OS setting to CSS. There are two ways to use it. The most robust is to opt in to motion: keep the interface still by default, and add animation only when the user has expressed no preference against it.

Opt-in approach (recommended)
/* Motion is added only when the user has NOT asked to reduce it */
@media (prefers-reduced-motion: no-preference) {
  .card {
    transition: transform 200ms ease;
  }
  .card:hover {
    transform: translateY(-4px);
  }
}

If retrofitting an existing codebase where motion is already scattered everywhere, a global reduce block is a pragmatic safety net. It near-instantly collapses animations and transitions when reduce is set, without touching every rule by hand:

Global safety net (retrofit)
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
Why 0.01ms and not 0? Setting the duration to a hair above zero rather than removing the animation keeps animationend and transitionend events firing — so any JavaScript waiting on them (to reveal content, advance a step, clean up) still runs. A hard animation: none can leave those listeners hanging and break the flow.

// 04 · handling motion in javascript

Handling Motion in JavaScript

CSS covers transitions and keyframes, but JavaScript-driven motion — a smooth-scroll call, a physics animation, an auto-playing sequence — has to check the preference itself. Read it with matchMedia and branch:

Checking the preference in JS
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');

function scrollToSection(target) {
  target.scrollIntoView({
    behavior: reduceMotion.matches ? 'auto' : 'smooth',
  });
}

// React to changes without a page reload
reduceMotion.addEventListener('change', () => {
  if (reduceMotion.matches) stopAutoplay();
});

Read the value at the moment you animate rather than caching it once at load, and listen for the change event so the interface responds if the user flips the setting mid-session. The same check gates auto-advancing carousels, animated counters, confetti, and any effect you drive from script.

// 05 · the usual offenders

The Usual Offenders

A few patterns cause most motion-related complaints. Each has an accessible version.

  • Auto-advancing carousels. They violate 2.2.2 unless users can pause them, and the movement distracts everyone. Provide a visible pause control, stop on hover and focus, and do not auto-advance at all under reduced motion. See the carousel pattern for an accessible build.
  • Parallax scrolling. Backgrounds moving at a different speed from foreground content is a classic vestibular trigger. Disable the parallax entirely under reduced motion and let the layers scroll together.
  • Full-screen transitions. Page or route changes that slide or zoom the whole viewport. Replace them with a quick cross-fade, or an instant change, when motion is reduced.
  • Autoplaying video and background loops. Motion that starts on its own and runs more than five seconds needs a pause/stop control (2.2.2). Prefer not autoplaying, and respect reduced motion by showing a static poster frame.
Reduced motion is not an excuse to skip pause controls 2.2.2 applies regardless of the user's motion preference — a carousel still needs a pause button even for users who have not reduced motion. Treat prefers-reduced-motion as an additional layer on top of the baseline controls, not a replacement for them.

// 06 · a safe default strategy

A Safe Default Strategy

Pulling it together into a policy you can apply consistently:

  • Keep motion small and purposeful by default. Short durations (under ~300ms), gentle easing, movement that communicates something (where a panel came from, that an item was added).
  • Under reduced motion, replace movement with a fade or an instant change — do not just delete the transition and leave a jarring snap. A 150ms opacity fade reads as calm, not broken.
  • Never rely on motion alone to convey meaning. If an animation signals success or an error, back it with text and an ARIA live region so it survives motion being reduced.
  • Provide explicit controls for anything auto-playing, independent of the OS setting, to satisfy 2.2.2.
  • Avoid rapid flashing entirely to stay clear of 2.3.1.
Reduce, then re-check meaning After you wire up reduced motion, turn the setting on and walk the key flows. The question is not "does it still look nice?" but "is any essential information lost?" If a state change that was only communicated by movement now happens invisibly, add a non-motion cue.

// 07 · common mistakes

Common Mistakes

  • Ignoring prefers-reduced-motion altogether. The most common failure — animations play the same for everyone regardless of the setting.
  • Deleting motion instead of reducing it. A hard cut to no animation can feel broken; a quick fade preserves polish while removing the trigger.
  • Auto-playing carousels with no pause control. A direct 2.2.2 failure, and a distraction for everyone.
  • Motion as the only signal. A shake to mean "error" or a slide to mean "saved", with no text equivalent, disappears when motion is reduced.
  • Rapid flashing. Any content flashing more than three times per second — a seizure risk that no preference setting excuses.
  • Checking the preference once at load. Not listening for the change event, so the UI ignores a mid-session toggle.
Where this fits Motion sits alongside the other visual-design criteria — pair this with the color and contrast guide and run it through the design review checklist. For the full WCAG 2.2 picture, see the WCAG 2.2 overview.

Frequently asked questions

What is prefers-reduced-motion?

prefers-reduced-motion is a CSS media feature that reflects an operating-system setting where users can ask software to minimize non-essential animation (macOS "Reduce motion", Windows "Show animations", and equivalents on iOS/Android). When it is set, @media (prefers-reduced-motion: reduce) matches, letting you turn off or tone down transitions and animations for the people who requested it — without affecting everyone else.

Does WCAG require respecting reduced motion?

Several criteria touch motion. 2.2.2 Pause, Stop, Hide (Level A) requires a way to pause or stop any motion that starts automatically, lasts more than five seconds, and runs alongside other content. 2.3.1 Three Flashes (Level A) forbids content that flashes more than three times per second. 2.3.3 Animation from Interactions (Level AAA) asks you to let users disable motion triggered by their own actions — which honoring prefers-reduced-motion satisfies. Even where it is only AAA, respecting the setting is a low-cost, high-impact win.

Should I remove all animation when reduced motion is set?

No — reduce, do not necessarily remove. The problem is large movement: parallax, sliding panels, zooming, spinning, things flying across the screen. These can trigger nausea and dizziness in people with vestibular disorders. Gentle opacity fades and instant state changes are usually fine and can even aid comprehension. A good reduced-motion default replaces big movement with a quick fade or an instant change, rather than making the interface feel broken and static.

What kinds of animation cause accessibility problems?

The riskiest are large-scale movement effects: parallax scrolling, full-screen transitions that slide or zoom, auto-advancing carousels, background video, and anything that spins or bounces continuously. For people with vestibular disorders these can cause real physical symptoms — dizziness, nausea, migraine. Flashing content (more than three flashes per second) is a separate, serious hazard that can trigger seizures. Small UI affordances like a button hover or a subtle fade are generally low-risk.

How do I test reduced motion?

Turn the OS setting on and browse your site. On macOS: System Settings → Accessibility → Display → Reduce motion. On Windows: Settings → Accessibility → Visual effects → Animation effects. Browser dev tools can also emulate it (Chrome/Edge: Rendering panel → "Emulate CSS media feature prefers-reduced-motion"), which is the fastest way to check without changing your system. Then confirm that essential meaning is not lost when motion is reduced.