Search topics
Animations that ignore the reduced-motion setting
Animations started by scrolling, opening a drawer, modal or accordion, or any other action never check the reduced-motion setting, and nothing else on the page turns them off.
The problem
People with vestibular disorders get dizzy or sick when every scroll sends blocks of content sliding up the screen, and they have no way to stop it.
A shop's "About us" page tells its story in five sections. As the visitor scrolls, each section starts lower down, invisible, then fades in while sliding up into place. Many marketing pages and site templates work this way, often through an "animate on scroll" library, and the content is always moving while the visitor scrolls. The same failure turns up in drawers that slide in, modals that zoom open, accordions that glide open and carousels that sweep sideways; this guide uses the scroll reveal because it is the most common. A visitor has turned on Reduce motion in their operating system because movement like this makes them dizzy. Every section still rises in.
Success Criterion 2.3.3 Animation from Interactions (Level AAA) asks that motion animation triggered by interaction can be disabled, unless the animation is essential to the function or the information. Scrolling is an interaction, and the Understanding document names scroll-triggered movement and parallax as examples. The slide-in adds nothing the content needs: the text says the same thing whether it arrives or is simply there. The stylesheet and the script never check prefers-reduced-motion, and the page offers no switch of its own, so there is no way to turn the movement off.
People with vestibular disorders, migraine or concussion can feel dizziness, nausea or headache from large movement, parallax and zooming, sometimes for hours afterwards, and scroll-linked movement makes it worse because it never stops while they read. Many of them have already said what they need, once, in their system settings.
1 of 10 groups affected
- No vision (not affected)
- Low vision (not affected)
- Colour vision (not affected)
- No hearing (not affected)
- Hard of hearing (not affected)
- No speech (not affected)
- Motor (not affected)
- Reach, strength (not affected)
- Cognitive (affected)
- Seizures (not affected)
- Limited language, cognitive and learning abilities People with attention difficulties lose their place when content keeps moving.
A static scan sees a CSS class or a library include, not the movement it produces, and it can't judge whether movement is essential. Many scanners never scroll, so scroll-triggered animation never runs. AI-written fixes often add a reduced-motion block for CSS transitions and miss the library that drives the effect from JavaScript. Others "fix" it by removing the class that shows the section, so with motion reduced the content stays invisible at opacity: 0.
Try it
Turn Reduce motion on, then scroll the page below.
The switch stands in for the system setting. With it on, does anything still slide in as you scroll?
Broken Can you fix this?
About us
Scroll down to read our story.
How we started
Two friends, one small shop and a lot of seedlings.
What we grow
Houseplants raised in peat-free soil, close to home.
How we deliver
Plastic-free packaging, by bike within the city.
Who we work with
Local nurseries and a community garden.
Visit us
Open Thursday to Sunday, 10:00 to 18:00.
A recreated demo. The broken version is intentionally inaccessible.
The fix
Under reduced motion, show the content in place, from the system setting or a switch on the page.
- 1Every animation started by scrolling or interaction checks the reduced-motion setting, in CSS and in scripts.
- 2Reduce motion by removing the movement, not the content.
- 3A switch on the page, if you add one, starts from the system setting.
.reveal { opacity: 0; transform: translateY(80px); transition: opacity 800ms ease, transform 800ms ease;}.reveal.in-view { opacity: 1; transform: none;}Why this fix: Make motion opt-in
Every section moves for every visitor. Nothing asks whether the visitor wants less motion, and the page has no setting of its own.
The hidden, lowered starting state and the slide now exist only inside no-preference. When the system asks for reduced motion, or a browser can't report the setting, the sections are simply there. Nothing has to be undone, so an animation added later can't be forgotten. The observer script can stay as it is. If the effect comes from a library, turn on its own reduced-motion option as well, because many libraries set transforms from JavaScript, where this CSS can't reach them.
Both pass. The media query is a few lines, needs no interface, and respects a choice the visitor has already made for every site, but it only helps people who know about the system setting and are allowed to change it. The switch on the page reaches those people too, at the cost of a control to design, place and label, and a stored preference to read before anything moves. Choose the media query alone when the motion is light; add the switch when motion is a large part of the design, the site is used on shared machines, or visitors ask for it.
Reduce motion means removing movement, not removing content. Short fades, colour changes and instant changes are generally fine; slides, zooms, spins, parallax and long smooth scrolls are what to remove. Keep animation that is essential, such as a drag that follows the pointer.
The same approach covers every other component that moves. Each still opens, closes or changes; only the travel goes.
- Drawer: appears in place or fades, instead of sliding in.
- Modal: fades, instead of zooming or dropping open.
- Accordion: opens at once, instead of animating its height.
- Carousel: changes slides without sweeping sideways.
- Page transition: swaps views without sliding.
Content that starts at opacity: 0 and waits for a script is fragile in any mode: if the script fails or the observer never fires, the section never appears. Keep the hidden starting state inside @media (prefers-reduced-motion: no-preference), as the first fix does, or add it from the script.
Animation in JavaScript is where most misses are. Check scroll-reveal and parallax libraries, carousels, scrollIntoView({ behavior: 'smooth' }), scroll-behavior: smooth and route transitions in single-page apps, and turn on each library's own reduced-motion option. A blanket rule that sets every animation-duration and transition-duration close to zero is a useful safety net, but it does nothing about a script that moves things itself, and it can break code that waits for transitionend.
Motion that starts without interaction, such as autoplaying carousels and background video, is covered by 2.2.2 Pause, Stop, Hide rather than this criterion. It is worth turning off under reduced motion as well.
Verify the fix
4 checks.
Test with: Reduced motion, Keyboard, Mouse
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after adding a new animation or updating an animation library.
Limits
This is a starting pattern, not a guarantee for every application. 2.3.3 is a Level AAA criterion, so many conformance targets do not require it, but the reduced-motion setting is a direct request from the visitor and is cheap to honour. Which movements make someone unwell varies from person to person; testing with people who use the setting tells you more than any rule.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.