A slide-in panel looks smooth to most people. For someone with a vestibular disorder, it can bring on dizziness or nausea. Their OS already has a "Reduce motion" setting. Your CSS should listen to it.
Web HIG tip #9 (Quick #76 / HIG-A11Y-001): Respect prefers-reduced-motion — replace motion with instant state changes or minimal opacity fade.
Why it matters
Motion that's fine for one person can make another feel sick:
- People with vestibular disorders, migraines, or motion sensitivity turn on "Reduce motion" so large on-screen movement stops making them unwell
- Parallax, big slide-ins, zooming page transitions, and auto-playing carousels cause the most trouble
- If the page ignores the setting, people have no way to stop it, so they leave
- The fix is small: the browser already exposes the setting as a media query
The full HIG (§1.3, Reduced Motion & Animation Safety) makes this a mandatory HIG requirement, even though the matching WCAG criterion (2.3.3 Animation from Interactions) is Level AAA. Auto-playing carousels and looping motion also need a pause control under WCAG 2.2.2 Pause, Stop, Hide (Level A).
The rule of thumb
Ask: with "Reduce motion" turned on, does anything still slide, zoom, spin, or scroll by itself?
If yes, swap that motion for an instant change or a short fade.
/* Don't: the panel always slides in, whatever the user's setting */
.panel {
transform: translateX(100%);
transition: transform var(--duration-slow) var(--ease-out-momentum);
}
.panel.is-open {
transform: none;
}
/* Do: keep the slide by default, and swap it for a short fade when reduced motion is on */
@media (prefers-reduced-motion: reduce) {
.panel {
transform: none;
opacity: 0;
visibility: hidden; /* a closed panel must not catch clicks or focus */
transition: opacity var(--duration-base) linear,
visibility 0s linear var(--duration-base);
}
.panel.is-open {
opacity: 1;
visibility: visible;
transition-delay: 0s;
}
}
Motion started from JavaScript needs the same check:
document.querySelector("#to-pricing").addEventListener("click", () => {
// Check at click time, so a setting changed mid-session is respected
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
document.querySelector("#pricing").scrollIntoView({
behavior: reduceMotion ? "instant" : "smooth",
});
});
Use "instant", not "auto": "auto" follows your CSS scroll-behavior, so a site with html { scroll-behavior: smooth } would still glide.
Reduced motion doesn't mean no feedback. A button can still change color and a dialog can still fade in. What goes is the movement: sliding, scaling, bouncing, parallax, and smooth scrolling.
Do this instead
- Wrap slide, scale, and parallax effects so they're replaced under
prefers-reduced-motion: reduce - Use an instant state change or a minimal opacity fade as the reduced version, so the user still sees that something changed
- Turn off parallax, auto-playing carousels, decorative looping animations, and View Transitions morphing when reduced motion is on. Immersive storytelling surfaces have a narrow exception (§1.5), and they still need a calm equivalent
- Check the same setting in JavaScript before smooth scrolling or starting an animation
- Name the properties you animate instead of using
transition: all(Quick #85, tip #6), so it's clear what your reduced-motion rules need to cover
Quick check for your app
Turn on reduced motion: in Chrome DevTools, press Cmd/Ctrl+Shift+P, run "Show Rendering", and set "Emulate CSS media feature prefers-reduced-motion" to reduce, or use your OS setting. Then open a menu and a dialog, trigger a page transition, and click an in-page link. Nothing should slide, zoom, or smooth-scroll, and every state change should still be visible. A media query existing isn't the same as the motion actually calming down, so test it.
HIG.md §1.3 also includes a global CSS safety net that cuts animation and transition durations and turns off smooth scrolling under reduced motion. Treat it as a backstop, not a replacement for a calm version of each effect.
The Web HIG is a behavioral contract for how the web should behave, not a component library. Design systems define how it looks. The Web HIG defines how it behaves.
Top comments (0)