auditmysitev2.0.2

Invalid modern interaction attributes

inert/dialog-inert

WCAG success criterion
4.1.2 (level A)
Outcome class
Automatic. An automated check that can report a confirmed violation.
Area
Accessibility, Technical Robustness
Default severity
high
axe-core rule
modern-attribute-misuse

Why we flag this

Screen reader and keyboard users cannot reliably access dialogs, popovers, or disabled regions.

Broken popovertarget references, unnamed surfaces, or active focus inside inert regions.

What the rule checks

Scope. Dialogs (open <dialog>, role dialog/alertdialog) that are rendered (Rendered scope: aria-hidden does not hide them from sight).

Expectation. Fails for an open native <dialog> that is inert itself or through an ancestor: it is shown but cannot be focused, operated or perceived by assistive technology. For role=dialog the markup cannot tell an open dialog from a closed one, so review. Closed dialogs, dialogs not rendered, and inert background content next to a dialog pass.

Source. WCAG 2.2 SC 2.1.1 Keyboard and SC 4.1.2 Name, Role, Value; HTML Living Standard, the inert attribute and the dialog element

Detection: shared; needs dom, computed_style.

Failing example

The check reports a violation here. Corpus case aria_dialogs_live_broken, element dialog#survey-dlg. The page may contain further findings for other rules.

aria_dialogs_live_broken.htmlHTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Shopping cart - Example shop</title>
</head>
<body>
    <header>
        <p>Example shop</p>
    </header>
    <main>
        <h1>Shopping cart</h1>

        <!-- status/live-overridden: the cart status is switched off -->
        <div id="cart-status" role="status" aria-live="off">2 items in your cart</div>
        <!-- status/live-overridden (review): urgency changed, still announced -->
        <div id="stock-alert" role="alert" aria-live="polite">Only 1 left in stock</div>
        <output id="total" aria-live="assertive">Total: 59 EUR</output>

        <!-- dialog/name-missing and dialog/modal-unmarked: unnamed custom
             dialog without aria-modal -->
        <div id="coupon-dlg" role="dialog">
            <p>Enter your coupon code.</p>
            <button type="button" id="coupon-ok">Apply</button>
        </div>

        <!-- dialog/name-missing and dialog/focusable-missing: open native
             dialog without a name and without anything to focus -->
        <dialog open id="saved-dlg">
            <p>Your cart was saved.</p>
        </dialog>

        <!-- dialog/focusable-missing: named alert dialog, nothing to focus -->
        <div id="timeout-dlg" role="alertdialog" aria-modal="true" aria-labelledby="timeout-title">
            <h2 id="timeout-title">Session ending</h2>
            <p>Your session ends in one minute.</p>
        </div>

        <!-- inert/dialog-inert: an open dialog that is inert -->
        <dialog open inert id="survey-dlg" aria-label="Quick survey">
            <p>How was your visit?</p>
            <button type="button" id="survey-ok">Answer</button>
        </dialog>
        <!-- inert/dialog-inert (review): custom dialog under an inert ancestor;
             without styles it may as well be a closed one -->
        <div inert>
            <div id="help-dlg" role="dialog" aria-modal="true" aria-label="Help">
                <button type="button" id="help-close">Close</button>
            </div>
        </div>
    </main>
    <footer>
        <p>Example shop</p>
    </footer>
</body>
</html>

Passing example

The check passes here and reports nothing. Corpus case aria_dialogs_live_valid. The page may contain further findings for other rules.

aria_dialogs_live_valid.htmlHTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Shopping cart - Example shop</title>
</head>
<body>
    <header>
        <p>Example shop</p>
    </header>
    <main>
        <h1>Shopping cart</h1>

        <!-- Live regions with their default urgency, stated or implicit; a
             log may change its urgency -->
        <div id="cart-status" role="status" aria-live="polite">2 items in your cart</div>
        <div id="stock-alert" role="alert">Only 1 left in stock</div>
        <output id="total">Total: 59 EUR</output>
        <div id="activity" role="log" aria-live="assertive">Coupon applied.</div>
        <!-- aria-live off on an element that is no live region role -->
        <div id="ticker" aria-live="off">Prices include VAT.</div>

        <!-- Named modal dialog with a control, named by aria-labelledby -->
        <div id="coupon-dlg" role="dialog" aria-modal="true" aria-labelledby="coupon-title">
            <h2 id="coupon-title">Coupon</h2>
            <button type="button" id="coupon-ok">Apply</button>
        </div>

        <!-- Open native dialog named by aria-label, with a control -->
        <dialog open id="saved-dlg" aria-label="Cart saved">
            <p>Your cart was saved.</p>
            <button type="button" id="saved-ok">OK</button>
        </dialog>

        <!-- Closed native dialogs are not presented: no name needed, inert is
             harmless -->
        <dialog id="closed-dlg"><p>Not shown.</p></dialog>
        <dialog id="closed-inert-dlg" inert><p>Not shown either.</p></dialog>

        <!-- Inert background content next to the dialog is the intended use -->
        <div id="background" inert>
            <p>Recommended products</p>
        </div>
    </main>
    <footer>
        <p>Example shop</p>
    </footer>
</body>
</html>

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