( Perceivable / WCAG 1.3.1 )

Element role is missing required child elements

SeriousLevel AWCAG 1.3.1 — Info and Relationships

What is this issue?

An element has an ARIA role that the WAI-ARIA specification defines as a composite role (one that only functions as a container for a specific set of child roles), and none of its children carry any of those required roles. role="listbox" requires children with role="option"; role="tablist" requires children with role="tab"; role="radiogroup" requires children with role="radio", and so on.

This is a structural failure, not an attribute-level one. The parent role’s own attributes can be perfectly correct, and every individual attribute on the page can pass its own checks, but if the DOM structure underneath the composite role doesn’t contain the child roles that role is defined to hold, assistive technology has no way to interpret it as the composite widget it’s meant to be.

Why does this matter?

Composite ARIA roles like listbox and tablist exist to tell assistive technology “this is a group, and here’s how many related items are inside it, and where you are among them.” That entire relationship depends on the children actually carrying the roles the parent expects: a listbox with <div> children that never received role="option" is, to a screen reader, just a container with no identifiable contents at all.

The practical effect is a widget that looks and behaves correctly for a mouse user but tells a screen reader user nothing about its structure. A custom multi-select dropdown built as role="listbox" with unstyled <div> options might work perfectly with a mouse click, but a screen reader user navigating into it hears no indication of how many options exist, which one is currently focused, or that they’re inside a list at all; the entire orientation a native <select> provides for free simply isn’t there.

Who is affected?

  • Screen reader users: lose the count, position, and grouping information a composite widget is supposed to convey, hearing unstructured content instead of “option 2 of 5” or an equivalent orientation cue.

What users experience

Kwame uses JAWS on Windows to pick a shipping destination from a custom city-picker dropdown on a travel booking site. The dropdown is built as role="listbox" containing plain <div> elements for each city, none of which carry role="option". When Kwame opens the dropdown, JAWS announces “listbox” but nothing about its contents: no city names read out as list items, no count, no current selection. He has to abandon the custom listbox and use the browser’s find-in-page search to locate a city name visually instead, a workaround that doesn’t exist for a sighted mouse user scrolling the same dropdown.

How do I fix it?

Add the required child role to every element the composite role is meant to contain. This works because assistive technology builds its understanding of a composite widget from the parent-child role relationship the specification defines; once the children carry the expected roles, the browser’s accessibility tree exposes the full group, including item count and position, automatically.

Match each child role to what the parent role specifically requires (option for listbox, tab for tablist, radio for radiogroup) rather than assuming any generic role will do. If a wrapper element sits between the parent and its intended children, such as a <div> grouping options visually, either remove the intermediate wrapper from the DOM structure or give the required children the role directly regardless of nesting depth, and confirm with a screen reader that the relationship is actually recognized.

Code Examples

Before
<div role="listbox" aria-label="Destination city">
  <div>London</div>
  <div>Tokyo</div>
  <div>Nairobi</div>
</div>
After
<div role="listbox" aria-label="Destination city">
  <div role="option" aria-selected="false">London</div>
  <div role="option" aria-selected="false">Tokyo</div>
  <div role="option" aria-selected="true">Nairobi</div>
</div>

Adding role="option" to each child gives the listbox the child roles its specification requires, which is what lets assistive technology recognize the group’s full contents, count, and current selection instead of an unstructured container. aria-selected on each option is a required attribute of the option role itself, tracking which city (if any) is the current selection. Fixing the required-children structure and the required-attribute state usually go together in the same component.

Common Mistakes

Mistake: “The parent role is set correctly, so the widget should work.” The parent role only announces what kind of container this is; it doesn’t automatically infer anything about children that lack their own matching role. role="listbox" on the parent and plain, roleless <div> children produces an empty-sounding container regardless of how correct the parent’s own attributes are.

Mistake: “Any child role is fine as long as there’s something there.” Composite roles require specific child roles, not just the presence of some ARIA role. A listbox with children marked role="listitem" instead of role="option" still fails this check, since listitem belongs to a different composite pattern (list) entirely.

Mistake: “A wrapper div between the parent and its real children shouldn’t matter, since it’s just for styling.” An extra layer of DOM nesting between a composite parent and its intended children can break the required-children relationship in some assistive technology implementations, even when the wrapper carries no visible styling difference. Keeping required children as close to direct descendants as possible, or using aria-owns when a wrapper is unavoidable, is the more reliable pattern.

How RedFlag Detects This

Automated: axe-core rule, runs on every scan. RedFlag calls axe-core’s aria-required-children rule as part of every scan, restricted to the WCAG 2.0/2.1/2.2 A and AA rule set. The rule identifies every element with a composite role that the WAI-ARIA specification defines as requiring specific child roles, then checks whether any descendant (accounting for aria-owns relationships) carries one of those required roles, flagging the parent when none are found.

False negative: the rule confirms some correctly-roled children exist; it can’t confirm every intended child element actually got the role, so a listbox with five visual options where only one received role="option" passes this specific check even though four options are still invisible to assistive technology. False positive: a listbox or similar composite role that’s legitimately empty at the moment of the scan (for example, search results rendered before a query is entered) can be flagged even though the empty state is expected; this needs manual judgment on whether the component always renders content by the time a user interacts with it. Manual step: confirm every visual item inside the composite widget, not just some of them, carries the correct required child role.

Manual Testing

  1. Open the page in Chrome or Firefox with NVDA or JAWS running.
  2. Navigate into the composite widget (dropdown, tab strip, radio group) using the screen reader’s element or object navigation.
  3. Listen for the screen reader to announce the group’s contents with position and count information, such as “option 1 of 5,” as you move through the items.
  4. If the screen reader announces the parent role but nothing about the items inside it, or skips straight past the group’s contents, the required child roles are likely missing or incomplete.
  5. Open the browser’s accessibility inspector (Chrome DevTools → Elements → Accessibility pane) and confirm each visual item’s computed role matches what the parent composite role requires.

1.3.1 Info and Relationships: Information, structure, and relationships conveyed through presentation must also be available programmatically. A composite widget missing its required child roles is exactly this failure: the grouping relationship is visually obvious but structurally absent from what assistive technology can read.

4.1.2 Name, Role, Value: Every interface component must expose its role, name, and value. A composite parent with no correctly-roled children can’t expose a complete or accurate role to assistive technology, since the role’s own definition depends on those children being present.

ARIA element is missing a required parent role is the mirror-image structural check: a child role sitting outside the parent role it requires, instead of a parent role missing the children it requires.

ARIA role is invalid is a prerequisite this rule assumes is already correct; an invalid parent or child role produces a different, more foundational failure than a valid role missing its structural relationship.

ARIA attribute is not allowed for this role commonly appears in the same composite widget, since fixing required children (like adding role="option") often surfaces a follow-up need to also add that role’s own required attributes correctly.

ARIA attribute is not valid for the current role value shares the same theme of structural context determining an attribute or role’s validity, applied to conditions rather than parent-child relationships.

Element uses a deprecated ARIA role and ARIA attribute is prohibited for this role are common co-occurring issues in older custom widget components built before current ARIA composite-role patterns were established.

References

Frequently asked questions

Which ARIA roles have required child roles?

Composite roles that represent a container of related items, such as listbox (requires option children), tablist (requires tab children), radiogroup (requires radio children), and menu (requires menuitem, menuitemcheckbox, or menuitemradio children), among others defined in the WAI-ARIA specification.

Do the required children need to be direct children in the DOM, or can they be nested deeper?

They can be separated by certain "owned" structural wrapper elements the specification allows, such as a group role, but a plain, non-semantic wrapper div with no role can still break the required parent-child relationship in some assistive technology implementations, so keeping children as direct DOM descendants is the more reliable pattern.

What happens if a listbox is empty and genuinely has no options yet?

This depends on the real-world state, and axe-core flags a static scan of the page as it renders. A listbox legitimately empty at first render, such as search results before a query is typed, is a case for manual judgment rather than an automated failure your team should chase down for every possible loading state.

Can I use aria-owns instead of nesting the children directly in the DOM?

Yes. aria-owns lets a parent role reference child elements located elsewhere in the DOM as if they were nested inside it, which satisfies the required-children relationship without requiring the actual markup structure to change, useful when a component library renders children into a different DOM location than their logical parent.

Is this the same failure as a required ARIA attribute being missing?

No. A required attribute failure is about a missing state or property, like aria-checked, on a single element. A required children failure is structural, about a parent role missing the specific child roles the specification says it must contain, regardless of whether any of its attributes are correct.