auditmysitev2.0.2

Required child elements of an ARIA role are missing

aria/required-children-missing

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
medium
axe-core rule
aria-required-children

Why we flag this

Assistive technologies cannot resolve the relationship between the widget's parts.

e.g. role="tablist" without corresponding role="tabpanel" elements.

What the rule checks

Scope. Elements in the accessibility tree with an explicit role that has required owned elements (tablist, list, listbox, menu, table, grid, tree, ...); native tables and lists without role get their structure from HTML.

Expectation. Fails when such a container owns elements with roles, but none of the required ones (a tablist owning buttons instead of tabs, a menu owning buttons). Owning a required element directly, through generic wrappers or via aria-owns passes; so does a container without any owned element, one marked aria-busy=true (loading) and one with aria-expanded=false. Native tables and lists are not judged here. Hidden subtrees are out of scope.

Source. WCAG 2.2 SC 1.3.1 and SC 4.1.2; WAI-ARIA 1.2 section 5.2.6 (Required Owned Elements); ACT bc4a75

Detection: shared; needs dom, ax_tree.

Failing example

The check reports a violation here. Corpus case iframe_widget_rules, element iframe#widget [frame] ul#tabs. The page may contain further findings for other rules.

iframe_widget_rules.htmlHTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Iframe widget rules corpus case</title>
</head>
<body>
    <main>
        <h1>Widgets inside a same-origin iframe (#715)</h1>
        <!-- Like gov.cy and magyarorszag.hu: a consent/dialog widget rendered
             in an iframe. The dialog has no name, the tablist is built from a
             list, so its tabs sit in list items instead of the tablist. The
             frame document has no main landmark, no h1 and no skip link on
             purpose: those are page-level rules and must not be reported for
             a frame. -->
        <iframe id="widget" title="Consent widget" style="width:600px;height:400px;border:0"
            srcdoc="<!DOCTYPE html><html lang=&quot;en&quot;><head><title>Widget</title></head><body>
<div role=&quot;dialog&quot; id=&quot;consent-dialog&quot;><p>We use cookies.</p><button type=&quot;button&quot;>Accept</button></div>
<ul role=&quot;tablist&quot; id=&quot;tabs&quot;><li><a role=&quot;tab&quot; href=&quot;#one&quot; id=&quot;tab-one&quot;>One</a></li><li><a role=&quot;tab&quot; href=&quot;#two&quot; id=&quot;tab-two&quot;>Two</a></li></ul>
</body></html>"></iframe>
        <!-- Hidden from assistive technology: not audited. -->
        <iframe id="hidden-widget" title="Hidden widget" aria-hidden="true" style="width:300px;height:100px;border:0"
            srcdoc="<!DOCTYPE html><html lang=&quot;en&quot;><head><title>Hidden</title></head><body><div role=&quot;dialog&quot; id=&quot;hidden-dialog&quot;></div></body></html>"></iframe>
    </main>
</body>
</html>

Passing example

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

value_widgets_native.htmlHTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Native value widgets corpus case</title>
</head>
<body>
    <main>
        <h1>Native range, number and date inputs</h1>
        <!-- Native controls expose their value without aria-valuenow, and the
             day/month/year fields of a date input are the browser's (#656). -->
        <label for="volume">Volume</label>
        <input id="volume" type="range" min="0" max="10">
        <label for="zoom">Zoom</label>
        <input id="zoom" type="range" role="slider" value="3" min="0" max="10">
        <label for="qty">Quantity</label>
        <input id="qty" type="number">
        <label for="amount">Amount</label>
        <input id="amount" type="number" value="4">
        <input type="date" aria-label="Order date value">
        <label for="time">Pickup time</label>
        <input id="time" type="time">
        <label for="month">Billing month</label>
        <input id="month" type="month">
        <label for="week">Calendar week</label>
        <input id="week" type="week">
        <label for="appointment">Appointment</label>
        <input id="appointment" type="datetime-local">
        <label for="disk">Disk usage</label>
        <meter id="disk" value="0.6">60%</meter>
        <hr>
        <div role="slider" tabindex="0" aria-label="Custom with value"
             aria-valuenow="5" aria-valuemin="0" aria-valuemax="10"></div>
        <div role="slider" aria-label="Hidden custom slider" style="display:none"></div>
    </main>
</body>
</html>

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