← Read

Design · · 4 min read

Designing motion for people who asked for less of it

Reduced motion doesn't have to mean no motion. What prefers-reduced-motion covers, what WCAG asks for, and how to decide what stays, what changes and what goes.

When someone turns on "Reduce motion" in their operating system, your site can detect it with the prefers-reduced-motion media query. The right response is rarely "turn every animation off". It's to remove the motion that can make people unwell, and keep what helps them understand the interface.

This guide covers what the setting is for, what the accessibility guidelines say, and a simple way to decide what to do with each animation. The code comes from this site, which has a fair amount of motion to account for.

Who the setting is for

The main group is people with vestibular (inner-ear) disorders. W3C's guidance on Animation from Interactions describes reactions to motion including "dizziness, nausea and headaches", which can be serious enough to need bed rest to recover.

Others turn it on because motion distracts them, or simply because they don't like it. Either way, it's an explicit request, so it's worth honouring carefully.

webkit.org ↗Responsive Design for MotionThe WebKit team's introduction to prefers-reduced-motion, with examples of motion to reduce.

What WCAG asks for

Two success criteria are directly relevant:

  • 2.3.3 Animation from Interactions (Level AAA): "Motion animation triggered by interaction can be disabled, unless the animation is essential to the functionality or the information being conveyed." Its listed sufficient techniques include using the CSS prefers-reduced-motion query (C39) and checking the same query in JavaScript (SCR40).
  • 2.2.2 Pause, Stop, Hide (Level A): anything that moves, blinks or scrolls that "starts automatically", "lasts more than five seconds" and is "presented in parallel with other content" needs a way to pause, stop or hide it, unless it's essential.

Note the levels. 2.2.2 is Level A, the baseline, and it applies to everyone, not just people with the setting on. An endless logo marquee or animated shader background that plays next to your content needs a pause mechanism regardless of preferences. Reduced motion alone doesn't satisfy it.

Reduce, don't remove

Motion does two different jobs in an interface:

  1. Explaining: showing where something came from or went, like a menu opening from its button, or an item moving into a list.
  2. Decorating: adding character, like parallax, floating shapes, bounces and marquees.

Explanatory motion carries information. Take it away completely and a panel just appears, which can be disorienting too. Decorative motion carries none, so it's safe to drop.

For each animation, ask:

QuestionIf yes
Does it move a large area, zoom, spin or create parallax?Remove it, or replace it with a fade
Does it run on its own, in a loop?Stop it for reduced motion, and add a pause control for everyone
Does it explain a change of state?Keep the state change, shorten it, and swap movement for opacity
Is it a small change like colour or opacity on hover?Usually fine to keep

A crossfade is the most useful substitute: the state still changes visibly, but nothing travels across the screen.

Implementing it in CSS

The simplest pattern is to write motion only for people who haven't asked to reduce it:

@media (prefers-reduced-motion: no-preference) {
  .panel {
    transition: translate 300ms ease-out;
  }
}

The blunter pattern is a global off switch. This site has one:

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

It's a reliable safety net: nothing new can slip through. It also has a real cost worth knowing about. It removes harmless fades and colour transitions along with the movement, so some state changes become instant jumps. A more refined version keeps opacity and colour transitions and removes only movement. Start with the safety net, then refine the parts that feel abrupt.

Implementing it in JavaScript

Animations started from JavaScript, such as Web Animations, canvas and WebGL loops, and scroll effects, don't respond to CSS media queries. Check the preference in code:

const reduce = matchMedia("(prefers-reduced-motion: reduce)");

function openMenu() {
  if (reduce.matches) return showMenuInstantly();
  playBounceAnimation();
}

On this site, the phone menu's bouncing marbles do exactly this. With reduced motion on, they skip the bounce and appear in place.

Two details to get right:

  • Listen for changes. People can switch the setting while your page is open. Use reduce.addEventListener("change", …) for long-running loops such as shader backgrounds.
  • Stop the loop, don't just hide it. A requestAnimationFrame loop drawing to an invisible canvas still uses battery.

A checklist before you ship

  • Turn on reduced motion in your OS and use the site with it on.
  • Check anything that plays automatically, loops or lasts more than five seconds has a pause, stop or hide control for everyone (WCAG 2.2.2).
  • Remove parallax, zooms, spins and large movements when reduced motion is on.
  • Replace movement that explains something with a fade instead of deleting it.
  • Check JavaScript and canvas animations separately. CSS rules don't reach them.
  • Listen for the setting changing mid-session.

FAQ

Where do people turn on reduced motion?

It's an operating-system setting: for example "Reduce motion" in iOS and macOS accessibility settings, and the animation effects settings in Windows. Browsers pass it to websites through prefers-reduced-motion.

Does reduced motion mean no animation at all?

No. The goal is to remove motion that can cause discomfort. Opacity and colour changes, and short fades that explain a state change, are generally fine.

Is respecting prefers-reduced-motion a legal requirement?

WCAG 2.3.3, which this preference helps meet, is Level AAA, which most regulations don't require. WCAG 2.2.2 (pausing auto-playing motion) is Level A and is commonly part of legal accessibility requirements. Check the rules that apply to your organisation.

Do marquees and animated backgrounds need a pause button?

If they start automatically, run longer than five seconds and sit next to other content, yes: WCAG 2.2.2 requires a way to pause, stop or hide them.

Sources

More to read