ARIA required owned elements require child roles to work
Last updated:
Related Guides
ARIA required owned elements must include required child roles
Elements with certain ARIA parent roles must contain specific child roles or elements so assistive technology can expose the correct structure and behavior.
This shows up in widgets like menus, listboxes, tablists, trees, grids, and radiogroups.
Users of screen readers, voice control, and keyboards rely on these relationships to navigate and operate components.
Why It Matters
When a parent role is missing the required children, the widget loses meaning. A screen reader may announce a menu with no menu items, or a listbox with no options.
This breaks navigation, selection, and operation for people using assistive tech. It can also confuse users with cognitive disabilities who depend on consistent patterns.
Clear parent–child roles help keyboard and speech users target the right item and understand context.
Common Causes
- Applying a parent role (e.g., listbox, menu, tablist) but using generic div/span children without required roles.
- Placing child roles outside the required context (e.g., option not inside a listbox; tab not inside a tablist).
- Dynamically removing or reordering children so required owned elements are missing at runtime.
- Relying on
aria-ownsto stitch unrelated nodes without mirroring the visual/DOM order. - Misusing
aria-activedescendantwithout valid, present IDs of focusable descendants. - Implementing combobox patterns without a proper textbox and popup listbox with option children.
How to Fix
- Identify the widget role and its requirements.
- Consult the ARIA role definition for “required owned elements” and “required context role”.
- Ensure required children exist in the DOM.
- Examples (not exhaustive):
role="listbox"must ownrole="option"children.role="menu"must ownrole="menuitem", "menuitemcheckbox", and/or "menuitemradio".role="tablist"must ownrole="tab"; each tab controls arole="tabpanel".role="radiogroup"must ownrole="radio".role="tree"must ownrole="treeitem"(often nested).- role="grid"/"treegrid" must own
role="row"; rows own role="gridcell"/"rowheader"/"columnheader". role="combobox"requires a text input and an associated popup (typicallyrole="listbox"withrole="option"items).
- Match required context roles for children.
- Place child roles only inside valid parents (e.g.,
role="option"insiderole="listbox",role="tab"insiderole="tablist").
- Place child roles only inside valid parents (e.g.,
- Wire relationships with ARIA where structure isn’t obvious.
- Use aria-labelledby/aria-label for names,
aria-controlsto link tabs to tabpanels,aria-activedescendantto indicate the active option when focus stays on the container, andaria-describedbyfor additional hints. - Use
aria-ownssparingly. Prefer real DOM hierarchy; if used, ensure IDs are valid and order is logical. - For sets, use
aria-setsizeandaria-posinsetwhen items are virtualized or DOM order does not reflect the set.
- Use aria-labelledby/aria-label for names,
- Keep states and properties accurate.
- Update
aria-selected,aria-checked,aria-expanded, etc., as user interaction changes.
- Update
- Recommendation: Follow the ARIA Authoring Practices patterns for the widget you implement and keep the DOM, visual order, and ARIA relationships aligned.
How to Test
Keyboard
- Can you reach the widget with Tab?
- Can you move among owned items with the expected keys (e.g., Arrow keys in listbox/menu, Left/Right in tablist)?
- Does focus remain logical (on container vs. items) according to the pattern?
Screen reader
- Does the parent role announce correctly (e.g., “listbox”, “menu”, “tablist”)?
- Are child items announced with correct roles and states (option selected, menu item, tab selected)?
- If using
aria-activedescendant, is the active item announced as you navigate?
Structure and ARIA checks
- Inspect the DOM: required child roles are present and nested under the parent.
- Verify children are inside the required context role (no orphan tabs/options).
- Confirm IDs used in
aria-activedescendant,aria-controls,aria-labelledby, andaria-ownsexist and are unique. - For virtualized sets, aria-posinset/aria-setsize reflect correct positions and total count.
Mobile/touch
- Using a screen reader (VoiceOver/TalkBack), swipe through the component. Parent and children should be announced with correct roles, names, and states.
Good Example
A listbox with owned options and active descendant:
<div role="listbox" aria-label="Choose a fruit" tabindex="0" aria-activedescendant="opt-apple">
<div role="option" id="opt-apple" aria-selected="true">Apple</div>
<div role="option" id="opt-banana" aria-selected="false">Banana</div>
<div role="option" id="opt-cherry" aria-selected="false">Cherry</div>
</div>Bad Example
Parent role without required children:
<div role="listbox" aria-label="Choose a fruit">
<div class="item">Apple</div>
<div class="item">Banana</div>
<div class="item">Cherry</div>
</div>Quick Checklist
- Parent roles include all required owned elements for that widget.
- Child roles appear only within their required context roles.
- ARIA relationships (labelledby, controls, activedescendant, owns) reference valid IDs.
- DOM hierarchy matches the visual and logical order; minimize
aria-owns. - States/properties (selected, checked, expanded) update as interaction changes.
- Keyboard interaction follows the expected pattern for the widget.
- Screen readers announce correct roles, names, and states for parent and children.