auditmysitev2.0.2

Missing alternative for motion actuation

manual/motion-actuation

WCAG success criterion
2.5.4 (level A)
Outcome class
Manual. A tool cannot decide this check. The audit only points a person at it; it is never counted as automatically verified.
Area
Accessibility, Navigation & Operation
Default severity
medium
axe-core rule
motion-actuation

Why we flag this

Users who cannot move the device are excluded from the functionality.

Use of device-motion APIs without UI controls.

What the rule checks

Scope. Pages with an inline script that listens to devicemotion or deviceorientation.

Expectation. One needs_review (UNTESTED) note per page, at the root, when an inline script subscribes to device motion or orientation; never pass or violation. External scripts are invisible to a document check, so pages without such an inline script get no note.

Why a person has to decide. Whether a motion-triggered function also has a UI control and can be turned off needs a device and a human; the document only shows that motion events are subscribed.

Source. WCAG 2.2 SC 2.5.4 Motion Actuation

Detection: shared; needs dom.

Failing example

The check flags this for review. Corpus case interaction_manual_checklist. The page may contain further findings for other rules.

interaction_manual_checklist.htmlHTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Member area</title>
    <style>
        body { font-family: sans-serif; margin: 0; padding: 16px; color: #111; background: #fff; }
        a, button, input { display: inline-block; min-width: 44px; min-height: 44px; padding: 12px; box-sizing: border-box; margin: 4px; }
        .skip { position: absolute; left: -9999px; }
        .skip:focus { left: 16px; }
    </style>
</head>
<body>
    <a class="skip" href="#main">Skip to main content</a>
    <header><p>Example Club</p></header>
    <nav aria-label="Main">
        <a href="/" aria-current="page">Home</a>
        <a href="/events">Events</a>
    </nav>
    <main id="main">
        <h1>Member area</h1>

        <!-- manual/pointer-gestures: a swipe carousel -->
        <section aria-label="Photo gallery">
            <h2>Last season</h2>
            <div class="carousel" id="gallery">
                <p>Slide 1 of 3: the summer tournament.</p>
            </div>
            <button type="button">Previous photo</button>
            <button type="button">Next photo</button>
        </section>

        <!-- manual/re-authenticating, manual/no-timing, manual/help: a sign-in form -->
        <form action="/login" method="post">
            <h2>Sign in</h2>
            <p><label for="user">Member number</label> <input id="user" name="user" type="text" autocomplete="username"></p>
            <p><label for="pass">Password</label> <input id="pass" name="pass" type="password" autocomplete="current-password"></p>
            <p><button type="submit">Sign in</button></p>
        </form>

        <!-- manual/interruptions: a live region announcing updates -->
        <div role="status" aria-live="polite" id="news">Next event: Saturday.</div>
    </main>
    <footer><p>Example Club footer</p></footer>
    <script>
        // manual/motion-actuation: shake to refresh the photos
        window.addEventListener('devicemotion', function (event) {
            if (event.acceleration && event.acceleration.x > 20) { location.reload(); }
        });
    </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.