2.3.3 Animation from Interactions
Motion animation triggered by interaction can be disabled, unless the animation is essential to the functionality or the information being conveyed.
What this rule means
WCAG 2.3.3 requires that motion animations triggered by user interaction can be disabled. This applies to animations that occur when a user scrolls, clicks, types, hovers, or otherwise interacts with the page — such as parallax scrolling effects, zoom animations, page transition animations, scroll-triggered reveal effects, and hover state animations that involve movement.
The criterion focuses specifically on motion animation — visual changes involving movement from one position to another or changes in size. Simple color changes, opacity transitions, or highlighting do not trigger this requirement. An exception exists when the animation is essential to conveying information or to the functionality itself (such as a progress bar moving to show completion).
Why it matters
Users with vestibular disorders (including benign paroxysmal positional vertigo, labyrinthitis, and Meniere's disease) can experience severe physical symptoms from motion animations — dizziness, nausea, headaches, and disorientation. These symptoms can persist long after the animation ends and may prevent the user from using their device for hours.
The vestibular system in the inner ear helps the brain understand motion and spatial orientation. When visual motion on screen contradicts the body's actual position (as with parallax scrolling or swooping page transitions), it creates a sensory conflict that triggers these symptoms. Providing a way to disable motion animations is essential for these users to safely browse the web.
Related axe-core rules
There are no automated axe-core rules for this criterion. Motion animations are highly varied in implementation (CSS animations, JavaScript-driven transforms, scroll-linked effects, Web Animations API) and their relationship to user interaction cannot be determined through static analysis.
How to test
Testing requires interacting with the page and observing animation behavior under different settings.
- Interact with all elements on the page: scroll, click buttons, hover over elements, navigate between pages.
- Note all motion animations that occur in response to interaction: sliding, zooming, parallax, page transitions, scroll-triggered movements.
- Enable prefers-reduced-motion in your operating system settings and repeat all interactions.
- Verify that motion animations are eliminated or significantly reduced when prefers-reduced-motion is enabled.
- Check if the application provides its own animation toggle independent of the OS setting.
- Test on mobile devices by enabling "Reduce Motion" in iOS accessibility settings or "Remove animations" in Android developer options.
How to fix
Respect the prefers-reduced-motion media query and provide an application-level toggle for motion animations.
Respect prefers-reduced-motion
/* Default: smooth animations */
.card {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-4px) scale(1.02);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
.page-enter {
animation: slide-in 0.5s ease-out;
}
@keyframes slide-in {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
/* Reduced motion: remove movement, keep feedback */
@media (prefers-reduced-motion: reduce) {
.card {
transition: box-shadow 0.15s ease;
}
.card:hover {
transform: none;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.page-enter {
animation: fade-in 0.15s ease-out;
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
}
Application-level animation toggle
<div class="settings-panel">
<label class="toggle">
<input type="checkbox" id="reduce-motion"
onchange="setMotionPreference(this.checked)">
<span>Reduce motion animations</span>
</label>
</div>
<script>
function setMotionPreference(reduce) {
document.documentElement.classList.toggle(
'reduce-motion', reduce
);
localStorage.setItem('reduce-motion',
reduce ? 'true' : 'false');
}
// Restore preference on load
window.addEventListener('DOMContentLoaded', () => {
const pref = localStorage.getItem('reduce-motion');
const osPrefers = window.matchMedia(
'(prefers-reduced-motion: reduce)'
).matches;
if (pref === 'true' || (pref === null && osPrefers)) {
document.documentElement.classList.add('reduce-motion');
document.getElementById('reduce-motion').checked = true;
}
});
</script>
Disable parallax scrolling
/* Parallax effect */
.parallax-bg {
background-attachment: fixed;
background-position: center;
background-size: cover;
transform: translateZ(-1px) scale(2);
}
/* Remove parallax for reduced motion */
@media (prefers-reduced-motion: reduce) {
.parallax-bg {
background-attachment: scroll;
transform: none;
}
}
/* Also remove for application-level toggle */
.reduce-motion .parallax-bg {
background-attachment: scroll;
transform: none;
}
Common mistakes
- Ignoring the prefers-reduced-motion media query entirely — this is the primary mechanism for motion-sensitive users.
- Only reducing animation duration instead of removing motion (a fast swoosh is still a swoosh).
- Parallax scrolling effects with no way to disable them.
- Scroll-triggered animations (elements flying in from the side) that cannot be turned off.
- Page transition animations that involve sliding, zooming, or rotating without a non-animated fallback.
- Hover animations that move elements (translateY, scale) without providing a motion-free alternative.
- Not testing with prefers-reduced-motion enabled during development and QA.