2.3.3 Animation from Interactions

WCAG 2.2 · 2.3.3 AAA Operable

What it requires

Motion animation triggered by interaction can be disabled, unless the animation is essential to the functionality or the information being conveyed. "Motion animation" means animation that moves content — parallax scrolling, large slide or zoom transitions, content that flies in as you scroll or click. It does not mean a simple change of colour, opacity, or a small essential progress indicator.

In practice this means: if you add decorative movement that fires when a user scrolls, clicks, hovers, or otherwise interacts, you must give them a way to turn it off. The accepted technique is to honour the operating-system "reduce motion" preference via the prefers-reduced-motion media query, and/or to provide an in-page control.

  • People with vestibular disorders — large or parallax motion can cause dizziness, nausea, and disorientation severe enough to make a page unusable.
  • People with migraine or motion sensitivity — unexpected movement can trigger headaches or attacks.
  • People with attention or cognitive disabilities — animated content that moves while they read pulls focus and disrupts comprehension.

How to detect it

Concrete checks for Animation from Interactions
Check What to look for
Manual review Scroll, click, and hover through the page. Note any parallax, fly-in, slide, or zoom motion that responds to your interaction and is not essential.
Reduced-motion setting Enable the OS "reduce motion" preference, reload, and confirm the non-essential motion is removed or replaced with a non-moving alternative.
In-page control If the OS preference isn't honoured, check for a visible setting that pauses or disables the motion.
Automated tools Tools such as axe cannot reliably detect this — judging "essential" and feeling the motion both require human review.

How to fix it

  1. Identify every interaction-triggered animation and decide whether it is essential. Decorative parallax and scroll fly-ins almost never are.
  2. Wrap non-essential motion so it is suppressed when the user requests reduced motion, using the prefers-reduced-motion: reduce media query.
  3. Provide a still alternative — fade or instant change instead of movement — so no information is lost when motion is off.
  4. Where the OS preference can't be relied on, add a visible "reduce motion" toggle.
/* Decorative motion on by default */
.card { transition: transform .4s ease; }
.card:hover { transform: translateY(-12px) scale(1.04); }

/* Honour the user's reduced-motion request */
@media (prefers-reduced-motion: reduce) {
  .card { transition: none; }
  .card:hover { transform: none; }
}

Copy-paste tests

Automated coverage

There is no fully automated axe-core rule for 2.3.3 — deciding whether interaction-triggered motion is "essential", and whether a reduced-motion request is actually honoured, both require human judgement. Treat this as a manual review using the console check and steps below.

Run this in the browser console

console-2-3-3.js
// Read-only: surface elements likely to animate on interaction.
const suspects = [...document.querySelectorAll('*')].filter(el => {
  const s = getComputedStyle(el);
  const t = (s.transitionProperty + ' ' + s.willChange);
  return /transform|top|left|translate/.test(t)
      || s.animationName !== 'none'
      || /sticky|fixed/.test(s.position);
});
console.log('Possible interaction animations:', suspects.length);
console.table(suspects.slice(0, 50).map(el => ({
  tag: el.tagName, cls: el.className,
  transition: getComputedStyle(el).transitionProperty,
  animation: getComputedStyle(el).animationName
})));
suspects.forEach(el => el.style.outline = '2px solid magenta'); // visual only

What to check manually: scroll, hover, and click each highlighted element and judge whether the motion is essential — no script can decide that. Then enable the OS "reduce motion" setting, reload, and confirm the non-essential motion is genuinely suppressed (not just visually hidden while still moving).