prefers-reduced-motion is the CSS media query (and related JS signal) that lets users ask your site to cut non-essential movement; using it is the practical way to satisfy WCAG 2.3.3, Animation from Interactions. Disable parallax, large translations, autoplaying motion, and long staggers—keep short opacity fades when they aid comprehension without disorienting. The snippet, split rules, and testing steps below are what we ship on production motion work.
Reduced motion is not “turn the whole site off.” It is a negotiated default: remove the movements most likely to cause discomfort or distraction, preserve feedback that tells users what happened, and never make the reduced path a worse-designed experience than the full one.
What WCAG 2.3.3 actually requires
WCAG 2.3.3 (Animation from Interactions, Level AA) applies when motion animation triggered by interaction can disable—rather than merely pause—the mechanism unless the animation is essential to the activity or information the user requested. In plain terms: if hovering, focusing, clicking, or scrolling starts movement, users need a way to avoid that movement when they have indicated a preference for reduced motion.
The mechanism you provide is almost always platform-level: the operating system’s reduce-motion setting, exposed to the browser as prefers-reduced-motion: reduce. When that preference is on, your CSS and JavaScript should honor it. Essential motion—progress indicators that convey required state, or animations the user explicitly asked to play—can remain, but decorative movement should not.
This sits alongside your Core Web Vitals work rather than competing with it. Heavy motion is not only an accessibility issue; long sequences can also push interaction latency toward the 200ms INP threshold. The same discipline that keeps transitions light (see page transitions without killing INP) makes reduced-motion branches easier to reason about. Every motion web development engagement ships with a reduced-motion path from day one.
The CSS snippet
A common baseline is a global collapse of animation and transition durations when the user prefers reduced motion:
@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;
}
}This is a useful safety net: near-zero durations effectively skip motion while leaving states interactive. It is not a complete design strategy. !important overrides can also flatten motion you might have wanted to keep simple, and GSAP or other JS timelines will ignore CSS duration overrides entirely—they need their own branch. Prefer pairing the net above with intentional component rules: disable specific classes, kill parallax wrappers, and stop scroll-linked effects explicitly.
What to disable, what can stay
| Motion type | Under reduced motion | Notes |
|---|---|---|
| Parallax / scroll-linked offsets | Disable | Large positional movement tied to scroll is the classic discomfort trigger |
| Long translate entrances (offscreen → onscreen) | Replace with fade or instant | Distance is the problem more than opacity; keep timing short |
| Autoplaying video or looping decorative GIF | Pause / static poster | Do not force users to hunt for a pause control after the fact |
| Staggered list reveals (500ms+ cascades) | Collapse to instant or single short fade | Sequential delays read as instability when users want content now |
| Hover scale / large transform on cards | Reduce or remove transform | Keep a subtle border or color change if it communicates interactivity |
| Route / page crossfades | Instant swap | Navigation should feel immediate; decoration should not gate paint |
| Short opacity fade on status change | Usually keep | Non-spatial, brief, and helps confirmation without disorientation |
| Focus indicator transition | Instant is fine | Clarity of focus matters more than how it animates in |
| Loading spinner (essential progress) | May remain | Indicates required system state; simplify if it strobes or spins large areas |
Essential vs non-essential is a design decision, not a blanket CSS decision. Document the split in the handoff motion note—trigger, duration, easing, and reduced-motion behavior—so engineering is not improvising mid-build. That note is a required row in our Figma handoff checklist, and the timeline structure we recommend lives in GSAP motion systems in production.
JavaScript and framework notes
CSS cannot stop a GSAP timeline or a canvas loop. In JavaScript, read the preference with window.matchMedia('(prefers-reduced-motion: reduce)') before creating scenes—and listen for changes so a user who flips the OS setting mid-session is respected without a full reload. GSAP users can scope timelines with its matchMedia helpers so each condition registers its own defaults.
Framework router transitions need the same branch: if reduced motion is on, skip exit choreography and paint the destination immediately. Progressive enhancement keeps the no-JS path honest: content is visible by default, and motion adds atmosphere on top—not permission to read.
For hybrid CSS + JS sites, own each layer explicitly. CSS handles component state transitions in the media query; JS handles section timelines. Ownership rules are covered in GSAP vs CSS: when to use which so the same element is never animated by both stacks under different reduced-motion interpretations.
Testing reduced motion properly
Test at three layers:
- OS level: enable reduce motion in your operating system’s accessibility settings, relaunch or refresh the browser, and walk the real user paths—home, template, forms, checkout or contact. Confirm nothing waits on an animation you can no longer see.
- Browser emulation: use the devtools rendering or media emulation panels to force
prefers-reduced-motion: reducefor fast iteration; then still do one pass with the actual OS setting, because emulation can miss native media and OS-injected behavior. - Interaction timing: click through transitions with reduced motion on and off. Both paths should reach a useful paint quickly; the reduced path should never be a stuck state waiting on
transitionend.
Add a design QA checkbox for reduced motion alongside contrast and keyboard focus. Teams that only test the default motion profile discover failures in production.
Key takeaways
- WCAG 2.3.3 is real and testable: honor
prefers-reduced-motion: reducein CSS and JS, disable parallax and large spatial movement, and keep only brief, non-disorienting feedback. - Ship a global duration net plus intentional component rules; give GSAP and router transitions explicit branches. Test with the OS setting, not only devtools emulation—and treat the reduced path as a first-class design, not a degraded demo.
FAQ
Is prefers-reduced-motion required by WCAG?
WCAG 2.3.3 (Animation from Interactions) requires that motion triggered by interaction can be disabled when it is not essential. Practically, responding to the user’s reduce-motion preference is the standard mechanism. Failing to provide one risks a Level AA failure on pages where interaction starts significant movement.
Should I remove all animation when reduce is on?
No. Remove or collapse movement that is decorative, spatial, or long-running; keep short opacity or color feedback that helps users understand results. Essential indicators tied to required activity can remain as long as they do not reintroduce the discomfort the user asked to avoid.
Why doesn’t my CSS override stop the animation?
Because it is not CSS. GSAP, canvas, WebGL, and video elements run outside your cascade. Check those code paths for matchMedia branches, pause media elements, and stop scroll-linked plugins. A CSS-only fix that “works” in a static demo often fails the moment a timeline initializes.
Does reduced motion hurt conversion or engagement?
Users who enable it are asking for less movement, not less content. A well-designed reduced path presents the same information with less vestibular load. Removing the preference branch does not create engagement—it creates exclusion and can hide performance bugs you would otherwise fix for everyone.
How does reduced motion relate to Core Web Vitals?
They are complementary. Collapsing animations removes main-thread and compositor work for users who opted out, and the same short-sequence discipline keeps INP healthy for everyone else. If transitions are a known risk on your site, start with the patterns in page transitions without killing INP, then confirm the reduced branch on every pattern you keep.