ARIA roles that require particular child roles
role=list with no listitem, or role=tablist with no tab, is an incomplete widget. squirrel checks thirteen container roles for their children.
What a required child role is
Composite ARIA roles are containers, and the specification says what they must contain. A tablist holds tab elements. A list holds listitem elements. A menu holds menu items.
When the children are missing, assistive technology gets a container that promises a widget and delivers nothing. Screen readers commonly announce the container and then find no items to move between.
What squirrel checks
One check, aria-required-children, at severity error. It covers thirteen container roles: feed, grid, list, listbox, menu, menubar, radiogroup, row, rowgroup, tablist, table, tree and treegrid.
For each element with one of those explicit roles it looks for a satisfying descendant at any depth, and follows aria-owns from the container, its descendants and the elements they own. A descendant satisfies the container when its role is one of the required roles. That role is the first valid token of an explicit role attribute, or else the implicit role a native element carries under HTML-AAM:
<input type="radio">isradio, so native radios insiderole="radiogroup"pass, wrappers and all.<li>islistitemand<tr>isrow.<thead>,<tbody>and<tfoot>arerowgroup.<td>iscell, orgridcellinside a table withrole="grid"orrole="treegrid".<th>iscolumnheader, orrowheaderwithscope="row".<option>isoption.<article>isarticle.
A native wrapper such as <fieldset>, <details>, <optgroup> or <tbody> holds the required items rather than being one, so it satisfies the container only through the items inside it. An explicit role="group" or role="rowgroup" counts on its own.
An explicit role replaces the implicit one, so <li role="none"> is not a list item and <input type="radio" role="menuitemradio"> is not a radio. The exception is none or presentation on an element that is focusable or carries a global ARIA attribute: browsers ignore that role, and so does the check.
Elements inside <noscript> are skipped, as containers and as children: a browser with scripting enabled reads <noscript> content as plain text. See content inside noscript.
An empty container is skipped, on the assumption it is populated later. A finding needs the element to have at least one child element or some text.
- Fail with
N element(s) missing required child roles. Items read<tag>[role="<role>"]: needs child with role=<roles>, where<roles>joins the accepted child roles with|, up to ten with a count of the rest. - Pass with
All elements have required child roles, which is also what a page using none of these roles reports.
How to fix it
<div role="tablist" aria-label="Account settings">
<button role="tab" aria-selected="true" aria-controls="profile">Profile</button>
<button role="tab" aria-selected="false" aria-controls="billing">Billing</button>
</div>Give the container the children its role demands, or drop the role and let the native elements speak for themselves.
squirrel searches at any depth, so an intermediate wrapper does not trip the check, and it follows aria-owns to elements elsewhere in the document. It does not check the other half of the relationship: an element can be a DOM descendant and still not be owned by the container in the way the role expects. A widget that passes here can still be wrong in a browser.
| Rule ID | a11y/aria-required-children |
| Category | Accessibility |
| Scope | Per-page |
| Severity | error |
| Weight | 7/10 |
Enable / disable
Disable this rule
[rules]
disable = ["a11y/aria-required-children"]Disable all Accessibility rules
[rules]
disable = ["a11y/*"]Enable only this rule
[rules]
enable = ["a11y/aria-required-children"]enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.
Related rules
- a11y/aria-required-parent: the same relationship checked from the child upwards.
- a11y/aria-required-attr: the state attributes those children need.
- a11y/list-structure: native
<ul>and<ol>with the wrong children. - a11y/aria-roles: whether the role you typed exists at all.
Accessibility findings ship in every audit next to the SEO, performance and agent experience rules. See Website security scan with AI for how an agent works through a report.
References
Check your site
Run squirrel audit https://example.com and open the Accessibility section of the report. Each container is listed with the child role it is missing. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.