A parallax hero, a sliding carousel or an animated page transition can trigger real physical symptoms for someone with a vestibular disorder: dizziness, nausea, and disorientation.
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.

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-motionsupports 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)').matchesand adjusting behaviour accordingly, as shown above. A site that only guards its CSS@keyframesstill leaves JavaScript-driven motion untouched. - Forgetting autoplaying video. Background video is motion too, and a
reducepreference 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.
