auditmysitev2.0.2

Missing pause/stop/hide control

motion/infinite-animation

WCAG success criterion
2.2.2 (level A)
Outcome class
Hint only. An automated check that by design reports review hints only: its findings are marked for manual review, never as confirmed violations.
Area
Accessibility, Navigation & Operation
Default severity
medium
axe-core rule
pause-stop-hide

Why we flag this

Users with attention or cognitive impairments, and screen reader users, are distracted or disrupted by continuously running motion they cannot turn off.

`<marquee>` element without pause control, or an element with animation-iteration-count: infinite exceeding 5 seconds per cycle with no detectable pause control or prefers-reduced-motion support.

What the rule checks

Scope. Rendered elements with a running animation whose iteration count is infinite, and marquee elements.

Expectation. A review at the outermost endlessly animated element (one per group of siblings) when the page offers no control to pause or stop motion. A finite animation (iteration count 3) is not endless; an endless animation on an element that is not rendered moves nothing. A control labelled to pause or stop (button "Pause animation") is taken as the mechanism; whether it works is for a human. An animation started by a script after load counts like a static one. Review, not a violation: an animation may end within five seconds of the page's own logic, which the snapshot cannot see.

Source. WCAG 2.2 SC 2.2.2 Pause, Stop, Hide (moving content that lasts more than five seconds)

Detection: shared; needs dom, computed_style.

Failing example

The check flags this for review. Corpus case visual_motion_infinite, element div#spinner. The page may contain further findings for other rules.

visual_motion_infinite.htmlHTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Endless loading spinners without a pause control</title>
<style>
  body { color: #111111; background: #ffffff; }
  .spinner { width: 40px; height: 40px; border: 4px solid #333333; border-top-color: transparent;
             border-radius: 50%; animation: spin 1.2s linear infinite; }
  /* Three runs, then it stops: not endless. */
  .wiggle { width: 40px; height: 40px; background: #333333; animation: spin 1s linear 3; }
  @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
</style>
</head>
<body>
<header>
  <a href="#main" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Skip to main content</a>
  <p>Order tracking</p>
  <nav aria-label="Main"><a href="#main" aria-current="page" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Overview</a></nav>
</header>
<main id="main">
  <h1>Your order is being prepared</h1>
  <div><div id="spinner" class="spinner" role="img" aria-label="Loading"></div></div>
  <div><div id="finite" class="wiggle" role="img" aria-label="New"></div></div>
  <!-- Endless, but not rendered. -->
  <div style="display: none"><div id="hidden-spinner" class="spinner"></div></div>
  <!-- Dynamic: the class is added by a script after load. -->
  <div><div id="late-spinner" role="img" aria-label="Refreshing"></div></div>
  <p>We will send you an e-mail as soon as the parcel leaves our warehouse.</p>
</main>
<footer><p>Footer text</p></footer>
<script>
  window.addEventListener('load', function () {
    document.getElementById('late-spinner').className = 'spinner';
  });
</script>
</body>
</html>

Passing example

The check passes here and reports nothing. Corpus case visual_motion_infinite, element div#finite. The page may contain further findings for other rules.

visual_motion_infinite.htmlHTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Endless loading spinners without a pause control</title>
<style>
  body { color: #111111; background: #ffffff; }
  .spinner { width: 40px; height: 40px; border: 4px solid #333333; border-top-color: transparent;
             border-radius: 50%; animation: spin 1.2s linear infinite; }
  /* Three runs, then it stops: not endless. */
  .wiggle { width: 40px; height: 40px; background: #333333; animation: spin 1s linear 3; }
  @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
</style>
</head>
<body>
<header>
  <a href="#main" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Skip to main content</a>
  <p>Order tracking</p>
  <nav aria-label="Main"><a href="#main" aria-current="page" style="display: inline-block; min-width: 44px; min-height: 44px; line-height: 44px; padding: 0 8px">Overview</a></nav>
</header>
<main id="main">
  <h1>Your order is being prepared</h1>
  <div><div id="spinner" class="spinner" role="img" aria-label="Loading"></div></div>
  <div><div id="finite" class="wiggle" role="img" aria-label="New"></div></div>
  <!-- Endless, but not rendered. -->
  <div style="display: none"><div id="hidden-spinner" class="spinner"></div></div>
  <!-- Dynamic: the class is added by a script after load. -->
  <div><div id="late-spinner" role="img" aria-label="Refreshing"></div></div>
  <p>We will send you an e-mail as soon as the parcel leaves our warehouse.</p>
</main>
<footer><p>Footer text</p></footer>
<script>
  window.addEventListener('load', function () {
    document.getElementById('late-spinner').className = 'spinner';
  });
</script>
</body>
</html>

This page is generated from the rule catalogue and the rule contracts; see therule overview for how the outcome classes are derived.