Motion That Respects the Reader: prefers-reduced-motion
Motion can make some people dizzy or sick, so a prefers-reduced-motion media query stops the loops and calms the movement for every reader who asks for less, while keeping the motion that helps.
Journeyman · CSS · Updated
After this lesson you can
- Write a prefers-reduced-motion media query that stops loops and shortens or removes movement
- Tell motion that helps, such as feedback or showing where something went, from decoration, and decide what to keep for reduced motion
- Turn on reduced motion in the developer tools or the system settings to test a page
Key takeaways
- Big or endless motion can make people with a vestibular (inner ear and balance) disorder, a migraine or a concussion dizzy or sick, and it distracts many others.
- Readers ask for less motion in their system settings, and @media (prefers-reduced-motion: reduce) applies rules only for them.
- For reduced motion, stop the loops, swap slides and zooms for a short fade, and shorten what's left. Color changes and small feedback can stay.
- Motion that helps gives feedback or shows where something went. Motion that only decorates is the first to go.
- Test it in Chrome or Edge with the Rendering panel's prefers-reduced-motion setting, or turn on reduced motion in your system settings.
Some people can't read in a moving car without feeling sick. For some readers, a web page can do the same thing: a background that slides as they scroll, a title that swoops in, a screen of stars that never stops twinkling. Phones, tablets and computers all have a setting that says "please, less motion", and many people turn it on. When you add motion to a page, this lesson is the other half of the job: it's how the motion you add helps everyone and hurts no one. It's also something reviewers and accessibility checks look for, in a class project or at work.
Why motion can make people sick
Inside your ear, a small balance system tells your brain how you're moving. When your eyes see movement that your balance system doesn't feel, like a page zooming past while you sit still, the two disagree, and that disagreement is what makes car sickness.
For people with a vestibular disorder (a problem with that inner-ear balance system), the disagreement can be much stronger. Large movements, zooms, spins and backgrounds that move at a different speed from the page can bring on dizziness, nausea or a headache that lasts for hours. A migraine or a concussion can make motion hard to bear for a while too. And for many readers, including people with attention difficulties, a loop that never stops makes it hard to focus on the words.
None of this means "no motion". It means motion that's small, short and there for a reason, and less of it for anyone who asks.
Asking the reader's settings: prefers-reduced-motion
Readers choose less motion in their system settings: Animation effects on Windows, Reduce motion on a Mac or an iPhone, Remove animations on many Android phones. The browser passes that choice on to your CSS as a media feature, the part of a media query in parentheses (from Media Queries and Breakpoints):
@media (prefers-reduced-motion: reduce) {
.star {
animation: none;
}
}
Read it as "at media, prefers reduced motion, reduce": for readers who asked for less motion, the stars don't animate. reduce means they asked; the other value, no-preference, means they didn't. Everyone else still sees the stars twinkle.
Put this media query after the rules it changes. A media query adds no specificity, so when its rule and an earlier rule tie, the one that comes later in the file wins.
What to change for reduced motion
"Reduced" doesn't have to mean "none". Go through the motion on the page and decide for each piece:
- Stop the loops. Anything that moves forever, such as twinkling, pulsing or a moving background, gets
animation: none. - Swap big movement for a fade. A title that slides in can fade in instead, in place. A fade still says "this is new" without anything moving across the screen.
- Shorten or remove small movement. A button that lifts can stay still and change color instead.
- Keep what has no movement. Color changes and fades are fine for nearly everyone.
@media (prefers-reduced-motion: reduce) {
.title {
animation: fade-in 200ms ease-out both;
}
.menu-button:hover,
.menu-button:focus-visible {
translate: none;
}
}
Here fade-in is a @keyframes rule with a single key moment, from { opacity: 0; }, so the title appears in its own place. And the buttons keep their hover color and shadow, so a reader still sees which one they're on.
You'll also see a safety net that calms everything at once:
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
The * selector picks every element, and !important lets these lines beat any other rule. Every animation and transition finishes almost at once and plays once. It's 0.01ms rather than 0s because a 0s transition never starts, so a script waiting for it to end would wait forever; a very short one still ends. It's a good backstop, but it's blunt: it removes the helpful motion too, so look at each piece as well.
The other way round: motion only for those who want it
You can also start with a calm page and add the motion only for readers who haven't asked for less:
@media (prefers-reduced-motion: no-preference) {
.star {
animation: twinkle 1.5s ease-in-out infinite alternate;
}
}
Now the stars twinkle only for no-preference, and a reader who asked for less motion, or whose browser is too old to know the setting, gets a still sky. Both ways are correct; this one makes the calm page the starting point.
Motion that helps, and motion that decorates
Before you keep a piece of motion, ask what it's for. Motion that helps tells the reader something:
- Feedback: a button that presses in when you click it says "got it"; a spinner says "it's working, wait".
- Showing where something went: an item that shrinks toward the cart, or a panel that slides out from the menu button, shows where to find it again.
- Drawing attention once to something new, such as a message that has arrived.
Motion that decorates is there because it looks nice: twinkling stars, a drifting background, a logo that spins. Decoration is fine on a game's start screen, but it's the first thing to stop for reduced motion. Helpful motion can stay, made smaller, shorter or a fade.
Two lines nobody should cross, setting or not: nothing should flash more than three times a second, which can cause seizures, and anything that starts moving by itself and keeps going for more than five seconds should have a way to pause, stop or hide it.
Test it in the developer tools
You don't have to change your system settings to test a page. In Chrome or Edge:
- Open the developer tools (F12).
- Press Ctrl+Shift+P (Cmd+Shift+P on a Mac) to open the Command Menu, type rendering, and choose Show Rendering.
- In the Rendering panel, find Emulate CSS media feature prefers-reduced-motion and choose prefers-reduced-motion: reduce.
While the developer tools are open, the page acts as if you'd turned the setting on. Check that every loop has stopped and that nothing slides or zooms, then set it back to No emulation.
Try it. Take a page with an animation, from the last lesson or a new one. Add a prefers-reduced-motion: reduce media query that stops it. Turn on the setting in the Rendering panel and check that it stops; set it back and check that it plays. Then turn reduced motion on in your own system settings and reload: the browser follows that too.
Check yourself
2 questions to try on the lesson page.
So what
Motion is a tool for telling the reader something, and some readers ask you to use less of it. One media query is how you hear them: stop the loops, calm the movement, keep the feedback, and the page works for everyone.