Prefers-Reduced-Motion: A Guide to Accessible CSS Motion

A Guide to Accessible prefers-reduced-motion

prefers-reduced-motion is the CSS media query that lets a website respect a choice the visitor has already made at the operating system level, and building a site without it means those effects are the default, not the exception.

macOS, iOS, Windows and Android all ship a system-wide “reduce motion” setting: macOS and iOS under Accessibility, Windows 11 under Accessibility, Windows 10 under Ease of Access, and Android under Accessibility as well. When someone turns that setting on, their browser exposes it to any website through the prefers-reduced-motion media query. A site that never checks for it never knows the visitor asked for something different.

Browser support is no longer a reason to wait. MDN lists prefers-reduced-motion as Baseline Widely available, which means it has worked across browsers since January 2020.

Pathzero - Dashboard

What prefers-reduced-motion actually does

prefers-reduced-motion is a CSS media feature with two possible values. no-preference means the visitor has not requested reduced motion, and your animations can run as designed. reduce means they have, and your CSS should respond by removing or substantially shortening non-essential motion.

A minimal implementation looks like this:

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

This blanket approach works as a starting point, but a more careful implementation treats each animation on its own terms rather than flattening all of them identically, which the next section covers.

Why a blanket fix is not always enough

Not every animation carries the same risk. A colour transition on a button hover causes no vestibular symptoms and can usually stay. Large-scale motion is the real concern: parallax scrolling, auto-playing carousels, animated backgrounds, and page transitions that involve significant movement across the screen.

The more considered approach is to keep small, low-risk transitions in place while removing or replacing anything involving large movement, scale changes, or continuous motion such as an auto-scrolling ticker. Where an animation communicates meaningful information, such as a loading state, replace the motion with a static equivalent rather than removing the feedback entirely: a visible label or icon that changes, instead of a spinner.

Checking reduced motion in JavaScript with matchMedia

A CSS media query only reaches CSS. For a carousel, a scroll-triggered effect or anything else started in script, read the same preference with window.matchMedia(). It returns a MediaQueryList, and its matches property is true when the visitor has asked for reduced motion:

const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');

if (!motionQuery.matches) {
  startCarousel();
}

motionQuery.addEventListener('change', (event) => {
  if (event.matches) {
    stopCarousel();
  }
});

The change listener matters because a visitor can switch the setting while your page is open, and a single check at load time misses that. startCarousel() and stopCarousel() stand in for your own code. MDN’s reference for matchMedia() covers the method in full.

In CSS, @media (prefers-reduced-motion) with no value is the same as @media (prefers-reduced-motion: reduce), because reduce is the only value that evaluates as true. The other value, no-preference, lets you work the other way round: write the calm version as your default and add motion only inside @media (prefers-reduced-motion: no-preference), so motion becomes something a visitor’s settings allow rather than something they have to turn off.

Common mistakes worth avoiding

  • Treating it as optional polish. prefers-reduced-motion supports Success Criterion 2.3.3, Animation from Interactions, part of the Web Content Accessibility Guidelines, and honouring a visitor’s stated preference is a baseline expectation, not a nice-to-have. 2.3.3 sits at Level AAA, above the AA level most policies target; our guide to WCAG 2.2 for UK businesses explains the levels and which one applies to you.
  • Only covering CSS animations. JavaScript-driven motion, such as a library-based carousel or a scroll-triggered animation, needs the same check performed in script, typically by reading window.matchMedia('(prefers-reduced-motion: reduce)').matches and adjusting behaviour accordingly, as shown above. A site that only guards its CSS @keyframes still leaves JavaScript-driven motion untouched.
  • Forgetting autoplaying video. Background video is motion too, and a reduce preference should pause autoplay or offer a static poster image in its place. Video is page weight as well, and a free website carbon audit shows your pages’ actual weight and modelled carbon per page view.
  • Applying it once and never revisiting it. A media query added when a site first launches does not automatically cover animations introduced later. Every new carousel, transition or scroll effect added during ongoing development needs the same check applied to it, which makes this worth a line in a build checklist rather than a one-off task ticked off and forgotten.

See our sustainable web design service for how motion, performance and accessibility get considered together rather than layered on afterwards.

Testing it yourself

You do not need a specialist tool to check this. On macOS, turn on Reduce Motion under System Settings, Accessibility, Motion, then reload your site. On Windows, the equivalent setting sits under Settings, Accessibility, Visual effects. With the setting enabled, every large-scale animation on your site should stop or shrink to something minimal; if nothing changes, the media query either is not implemented or does not cover that specific animation.

Most common questions

01

What does prefers-reduced-motion do?

`prefers-reduced-motion` is a CSS media query that detects whether a visitor has enabled a system-level setting asking for reduced motion, so a website can remove or shorten animations that would otherwise run by default.

02

Why does reduced motion matter for accessibility?

Large-scale motion, such as parallax scrolling or auto-playing carousels, can trigger dizziness, nausea and disorientation in people with vestibular disorders. Respecting `prefers-reduced-motion` prevents a website from forcing that experience on visitors who have already asked to avoid it.

03

Does prefers-reduced-motion mean removing all animation?

No. Small, low-risk transitions such as a button hover colour change can usually stay. The setting is aimed at large-scale motion: parallax effects, auto-playing carousels, continuous scrolling elements and significant page transitions.

04

Does prefers-reduced-motion cover JavaScript animations too?

Not automatically. CSS animations wrapped in an `@media (prefers-reduced-motion: reduce)` block are covered, but JavaScript-driven motion needs its own check, typically using `window.matchMedia('(prefers-reduced-motion: reduce)').matches` before running or setting up the animation.

05

Is prefers-reduced-motion a WCAG requirement?

W3C lists it as a technique for Success Criterion 2.3.3, Animation from Interactions, part of the Web Content Accessibility Guidelines. It is listed as a AAA-level criterion, above the AA baseline most accessibility policies target, but implementing it is low-effort relative to the harm it prevents.

06

How do I test whether my site respects prefers-reduced-motion?

Enable your operating system's reduce motion setting (Accessibility, Motion on macOS; Accessibility, Visual effects on Windows), then reload your site. Large-scale animations should stop or shrink noticeably. If nothing changes, the media query is either missing or does not cover that particular animation.