( Operable / WCAG 2.3.3 )

Page animations have no reduced motion alternative

ModerateLevel AAAWCAG 2.3.3 — Animation from Interactions

What is this issue?

The page contains CSS animation-name or transition declarations (parallax scrolling, sliding panels, zooming hero images, hover-triggered movement) with no accompanying @media (prefers-reduced-motion: reduce) rule anywhere in its stylesheets to reduce or disable that motion. prefers-reduced-motion is a CSS media feature that reflects a setting a user turns on once, at the operating-system level, and expects every site they visit to respect automatically.

This is distinct from the <blink>/<marquee>-style legacy motion covered elsewhere in this cluster; those are obsolete HTML elements with no modern justification at all. Interaction-driven CSS animation is legitimate, common, and often genuinely useful; the failure here isn’t that the animation exists, it’s that the page gives motion-sensitive users no way to opt out of it.

Why does this matter?

For someone with a vestibular disorder (a condition affecting the inner ear’s balance system), watching large-scale on-screen motion can trigger genuine physical symptoms: nausea, dizziness, and disorientation that persist well after they’ve looked away from the screen. This isn’t a metaphor for mild annoyance; it’s a physiological reaction to visual motion the same balance system interprets as movement of the body itself.

prefers-reduced-motion exists precisely because operating systems recognized this as a real, common need worth building a permanent, cross-site setting for. A user who enables it has explicitly told every site they visit, in the most direct channel available, that they need animation reduced. A page that ignores the setting isn’t failing to anticipate a preference, it’s actively overriding one the user went out of their way to set.

Who is affected?

  • Cognitive disabilities: motion sensitivity and vestibular symptoms are frequently comorbid with migraine and certain neurological conditions; unpredictable on-screen movement can trigger discomfort severe enough to make continued reading impossible.
  • Low vision users: some low-vision conditions and their common triggers, including certain forms of migraine with aura, are aggravated by large-scale visual motion in ways a reduced-motion fallback directly mitigates.

What users experience

Feliks has a vestibular disorder diagnosed after a car accident, and has prefers-reduced-motion enabled system-wide on both his phone and laptop, expecting every site he visits to honor it. He opens a real estate listing page with a parallax hero section where property photos shift at a different scroll speed than the surrounding text. The page never checks his reduced-motion setting, so the parallax effect fires exactly as designed the moment he starts scrolling, and within a few seconds he has to close his eyes and stop scrolling entirely to avoid nausea, abandoning the listing before he’s seen the property details he came for.

How do I fix it?

Wrap non-essential CSS animations and transitions in a @media (prefers-reduced-motion: reduce) block that removes or substantially shortens the motion. This works because the media query directly reflects the OS-level setting the user already turned on: no JavaScript detection or user-agent sniffing is needed, since the browser exposes the preference to CSS natively.

Apply this at the design-system level rather than per-component, so every new animated component inherits the fallback automatically instead of each developer remembering to add it individually. For essential motion (an animation that itself conveys necessary information, such as a loading spinner communicating that a process is still running), WCAG allows keeping some indication of state, but even then, prefer a version with less dramatic movement (a subtle pulse instead of a fast spin) over removing all feedback entirely.

Code Examples

Before
.hero-parallax {
  transition: transform 0.6s ease;
}
.card:hover {
  transform: scale(1.08) translateY(-12px);
  transition: transform 0.4s ease;
}
After
.hero-parallax {
  transition: transform 0.6s ease;
}
.card:hover {
  transform: scale(1.08) translateY(-12px);
  transition: transform 0.4s ease;
}

@media (prefers-reduced-motion: reduce) {
  .hero-parallax {
    transition: none;
  }
  .card:hover {
    transform: none;
    transition: opacity 0.2s ease;
    opacity: 0.95;
  }
}

The reduced-motion block removes the parallax transform entirely, since it has no functional purpose beyond visual flourish, and replaces the card’s scale-and-lift hover effect with a brief opacity change, keeping some hover feedback for sighted mouse users, but without the large-scale movement that risks triggering vestibular symptoms.

Common Mistakes

Mistake: “We don’t need this because our animations are subtle.” Vestibular trigger risk depends on the type and scale of motion relative to the viewport, not on subjective design intent: a “subtle” parallax or scale effect can still involve enough visual movement to cause discomfort for someone with a genuine sensitivity, even if it reads as tasteful in a design review.

Mistake: “Adding a reduced-motion query means removing all animation everywhere.” WCAG’s own guidance is to reduce or substantially shorten non-essential motion, not necessarily eliminate every visual transition. A quick opacity fade in place of a sliding or zooming effect often preserves enough visual continuity while cutting the actual trigger risk.

Mistake: “This only matters for people who know to enable an obscure OS setting.” prefers-reduced-motion is a standard, built-in accessibility setting in every major operating system’s settings panel, not a hidden developer flag; treating it as a niche edge case undersells how directly and deliberately affected users reach for it.

How RedFlag Detects This

Custom automated: RedFlag’s own DOM detector, runs on every scan. RedFlag’s runCustomRules engine computes the resolved style for every element on the page and flags the page (reporting up to three offending elements) if any element has a non-none animation-name or a transition-duration over 0.3 seconds, and no stylesheet on the page contains an @media rule with a prefers-reduced-motion condition anywhere in its text.

False negative: the check only confirms that some prefers-reduced-motion rule exists somewhere on the page; it can’t verify that the rule actually reduces the specific animation it’s paired with, so a reduced-motion block that only touches an unrelated element while leaving the real offender untouched still passes. False positive: cross-origin stylesheets throw an error when the script tries to read their rules and are silently skipped, so a page whose reduced-motion handling lives entirely in a CDN-hosted stylesheet the detector can’t access can be flagged even though the fallback genuinely exists. Manual step: enable prefers-reduced-motion at the OS level, reload the page, and confirm each animated element visibly reduces or removes its motion: this is the only way to verify the fallback actually works, not just that a matching media query exists somewhere in the CSS.

Manual Testing

  1. Enable reduced motion at the OS level: macOS System Settings > Accessibility > Display > Reduce Motion, or Windows Settings > Accessibility > Visual Effects > Animation Effects.
  2. Reload the page with the setting active and interact with every animated element: scroll past parallax sections, hover over animated cards, trigger any modal or panel transitions.
  3. Confirm each animation is visibly reduced, shortened, or removed compared to its normal-motion behavior; if any interaction still produces the full, unreduced animation, the check fails for that element.
  4. In Chrome DevTools, open the Rendering tab and use “Emulate CSS media feature prefers-reduced-motion” as an alternative to changing OS settings, useful for quickly testing multiple pages in sequence.

2.3.3 Animation from Interactions: Motion animation triggered by user interaction can be disabled, unless the animation is essential to the functionality or the information being conveyed. This rule is a direct check of whether a prefers-reduced-motion fallback exists to provide that disable mechanism.

Dragging interaction has no pointer alternative shares this rule’s concern with giving users control over interaction-driven behavior, applied to drag gestures rather than animation.

Page contains a blinking or scrolling element covers the legacy, obsolete-element version of uncontrolled motion; this rule’s modern CSS-animation equivalent extends the same “give users control over movement” principle to contemporary interaction design.

Page has no way to bypass repeated content, Page has no descriptive title, and Heading is empty or contains only whitespace are foundational structural checks worth running alongside a motion audit, since sites that skip reduced-motion support often haven’t had a full accessibility pass at all.

Focus order does not match the visual or DOM order is worth checking on any page with animated, JavaScript-repositioned elements, since animation and focus-order bugs frequently share the same root cause: DOM structure that doesn’t match what’s visually happening on screen.

References

Frequently asked questions

Is prefers-reduced-motion the same as pausing a flashing element?

No, they address different criteria. This rule concerns interaction-triggered motion, such as a parallax scroll effect or a sliding transition, under 2.3.3 Animation from Interactions. A flashing effect that can trigger seizures is a separate, more severe concern covered by redflag-flash (2.3.1), which has no relationship to the reduced-motion media query at all.

Does prefers-reduced-motion mean removing all animation entirely?

Not necessarily. WCAG recommends the media query reduce or remove non-essential motion; many teams keep a brief opacity fade in place of a sliding or zooming transition, since a fade carries far less vestibular trigger risk than movement across the screen while still giving some visual continuity.

How do I test what my own OS reduced-motion setting actually does?

On macOS, enable it under System Settings > Accessibility > Display > Reduce Motion; on Windows, under Settings > Accessibility > Visual Effects > Animation Effects. Once enabled, reload the page with DevTools open and confirm your CSS reduced-motion media query is actually applying, since the OS setting only changes anything if your site listens for it.

Does this rule apply to a single CSS transition, or only large animations?

It applies to any animation-name or transition lasting more than roughly 0.3 seconds, which includes small transitions like a hover-triggered scale or slide, not just large full-page effects. A subtle transition can still trigger discomfort for someone with a vestibular condition, even if it looks minor in a design review.

Is 2.3.3 a requirement most sites are legally required to meet?

Not usually. 2.3.3 Animation from Interactions is a Level AAA criterion, above the Level AA baseline most accessibility laws and organizational policies require. It is still worth implementing broadly, since a prefers-reduced-motion media query is inexpensive to add and directly prevents real physical discomfort for motion-sensitive users.