← Writing
5 min read

Motion accessibility beyond prefers-reduced-motion

The media query is the floor, not the finish line. What actually triggers vestibular symptoms, why blanket-disabling animation is the wrong fix, and the cases the query never covers.

  • accessibility
  • fundamentals

Most teams’ entire motion accessibility story is one media query, usually pasted from the same reset:

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

That is a reasonable floor and better than nothing. It is not the finish line, and treating it as one leaves real problems in place, including some it causes.

What actually causes harm

The population this matters for is larger than most people assume: vestibular disorders affect a substantial share of adults, and the symptoms are real: nausea, dizziness, migraine, disorientation lasting well beyond the page visit.

What triggers it is specific, and it is not “animation” in general:

Large-area movement. Motion occupying much of the visual field is the biggest factor. A full-screen slide is a problem in a way a 4px button nudge never is.

Parallax. Layers moving at different speeds is one of the strongest triggers, because it directly simulates depth cues the inner ear expects to accompany with real head movement.

Movement the user did not initiate. Autoplaying carousels and unprompted animation are worse than motion the user caused, because there is no opportunity to brace.

Spinning and rotation. Especially large or sustained.

Scaling from very small to very large, which reads as rushing toward the viewer.

Note what is not on that list: opacity fades, colour transitions, small movements, brief state changes. Fading is not a vestibular trigger. This is why the blanket reset overshoots. It removes safe motion along with harmful motion, and in doing so removes information.

Reduce, not remove

The setting is named “reduce” deliberately. The user is not saying show me no animation; they are saying do not move me through space.

The better treatment keeps the meaning and drops the movement:

.panel {
  transition: opacity 200ms var(--ease-out),
              transform 250ms var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
  .panel {
    transition: opacity 200ms var(--ease-out);   /* keep the fade */
    transform: none;                             /* drop the travel */
  }
}

The user still perceives that a panel appeared. They are simply not flown into position to learn it. That is strictly more usable than an instant pop, which loses the change-of-state signal that made the animation worth having.

Same logic elsewhere: a shared element transition becomes a crossfade rather than nothing. A staggered list arrives at once with a fade rather than snapping. A loading spinner becomes a pulsing or static indicator rather than disappearing, because the user still needs to know something is happening.

The bug the blanket reset causes

Ironically, the most common accessibility failure in this area is created by the reset itself.

A reveal-on-scroll pattern usually starts at opacity: 0 and animates to 1. Kill the animation with animation-duration: 0.01ms and the element still has opacity: 0 from the base rule, so the animation now completes instantly at its from state and never applies the to.

The content is invisible. To exactly the users who enabled the setting.

/* The fix: reset the properties, not just the timing. */
@media (prefers-reduced-motion: reduce) {
  .reveal {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

The general rule: content must be visible and usable by default, with motion added on top. Then no setting, unsupported browser, or JS failure can hide anything.

What the media query never covers

prefers-reduced-motion is an OS setting. Plenty of affected people have never found it, are on a borrowed device, or are having a bad day on a system where it is off.

Three things it does not address at all:

Autoplaying content. WCAG is explicit: anything moving automatically for more than five seconds needs a pause control. A looping hero video, an auto-advancing carousel, an ambient background: all of them need a visible way to stop. This is a requirement, not a preference, and it applies regardless of any OS setting.

Flashing. Content flashing more than three times per second can trigger seizures. This is the one hard line in the whole subject.

Interruptibility. An animation the user cannot skip is an animation they must endure. Long transitions with no escape are an accessibility problem even when perfectly smooth.

Motion and focus

The overlooked interaction: animation and keyboard navigation.

If a focused element animates into position, focus can land somewhere the user cannot see, or a screen reader can announce an element before it visually exists. During a long transition, keyboard users may tab into content that is still moving or not yet interactive.

Practical guidance: keep focus-related motion short (under 150ms) and set focus after a transition completes rather than during it. And ensure the focus ring itself never animates in a way that makes it hard to locate; that ring is the entire navigation model for keyboard users.

Testing

  • Turn the setting on and use the product for a day. Not one page, the whole flow. This surfaces the invisible-content bug immediately.
  • Check every autoplaying thing has a pause control.
  • Tab through everything that animates. Watch where focus goes.
  • Scroll fast on mobile. Reveal animations that look elegant at reading speed often look broken at scrolling speed, and produce a page of half-visible text.

The framing that helps

Motion accessibility is usually presented as a constraint on design. It is more useful to treat it as the same discipline that makes motion good in the first place.

Every rule here (smaller movements, shorter durations, user-initiated rather than automatic, interruptible, informative rather than decorative) is also just good interface motion. The animations that hurt people are, with few exceptions, the ones that were too big, too long, and too pleased with themselves anyway.

Designing for the vestibular case tends to produce a better product for everyone. That is not a consolation; it is the reason to start there.