Reduced motion
Respect the user's `prefers-reduced-motion` setting. Decorative animation, parallax, and autoplay can trigger vestibular distress, migraines, and seizures.
What it is
Some users have signalled at the operating-system level that they want motion on screen reduced. The browser exposes that signal through the prefers-reduced-motion media query. When the value is reduce, the user is asking you to remove or shorten non-essential animation.
@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 it matters
Uncontrolled motion is not a taste issue. It causes real harm:
- Vestibular disorders. Parallax, zooming transitions, and long slide-ins can trigger nausea, dizziness, and disorientation that lasts for hours.
- Migraine and photosensitivity. Looping background video and flashing transitions are common triggers.
- Seizure risk. Anything flashing more than three times per second is a WCAG Level A failure (2.3.1).
WCAG 2.2.2 Pause, Stop, Hide (Level A) requires that any moving, blinking, scrolling, or auto-updating content lasting more than five seconds can be paused or stopped. WCAG 2.3.3 (Level AAA) goes further: motion triggered by interaction must be disableable unless essential to the function.
How to implement
Cover both CSS animations and JavaScript-driven motion.
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)');
if (!reduce.matches) {
startCarousel();
}
reduce.addEventListener('change', (e) => {
e.matches ? stopCarousel() : startCarousel();
});
Apply the same logic to native media:
<video autoplay muted loop playsinline>...</video>
Autoplaying background video should be gated on prefers-reduced-motion: no-preference, or shipped as a static poster image by default.
Distinguish decorative motion from meaningful motion. A spinner that says “loading” still needs to communicate; replace the spin with a static “Loading…” label or a very slow pulse. A tutorial transition that shows where a panel came from can be shortened to a fade rather than removed.
The worst offenders to audit first:
- Parallax scrolling.
- Large zoom or slide-in transitions on scroll.
- Autoplay carousels and sliders.
- Looping background video.
- Confetti, particle effects, and infinite marquees.
Browser support is universal across Chrome, Edge, Safari, and Firefox.
Common mistakes
- Treating reduced motion as optional polish. It is a required accessibility behaviour.
- Removing transitions but leaving autoplay video running.
- Hiding the pause control behind a hover state on a touch device.
- Animating in JavaScript with no
matchMediacheck, so CSS overrides do nothing.
Verification
- In macOS System Settings, enable Accessibility → Display → Reduce motion. Reload the page. Decorative animation should stop.
- In Chrome DevTools, open the command menu and run Emulate CSS prefers-reduced-motion: reduce.
- Confirm any motion longer than five seconds has a visible pause, stop, or hide control (WCAG 2.2.2).
- Confirm no content flashes more than three times in any one-second window.
Related topics
Sources & further reading
- WCAG 2.3.3 — Animation from Interactions (Level AAA) — W3C
- WCAG 2.2.2 — Pause, Stop, Hide (Level A) — W3C
- MDN — prefers-reduced-motion — MDN
- WP Accessibility — WP Accessibility
- web.dev — prefers-reduced-motion: Sometimes less movement is more — web.dev