Skip to main content
Accessibility AccessLint 0.16

Certain ARIA roles must be contained within specific parent roles.

About this AccessLint rule

Certain ARIA roles are defined as items that must appear inside a specific parent role in the accessibility tree. For example, an element with role="listitem" must be a child of an element with role="list", and an element with role="tab" must be a child of an element with role="tablist". When these parent-child relationships are missing, assistive technologies cannot determine the structural context of the element, and the information they convey to users becomes incomplete or wrong.

Screen reader users are the most affected. Screen readers rely on the accessibility tree to communicate structure. A tab that exists outside a tablist, or a row that exists outside a table or grid, loses its semantic meaning. A screen reader might announce the element's role without any surrounding context, or skip it entirely. Users then have no way to understand how the element relates to the rest of the page.

This rule maps to WCAG 2.0+ Success Criterion 1.3.1 "Info and Relationships" (Level A), which requires that information, structure, and relationships conveyed through presentation are programmatically determinable. When a required parent role is missing, the structural relationship between the child and its container is not programmatically determinable.

How the accessibility tree works here

The required parent-child relationship is evaluated in the accessibility tree, not the DOM tree. This distinction matters. Some intermediate DOM elements may have role="presentation" or role="none", which removes them from the accessibility tree. In that case, the accessibility tree "looks through" those elements. An element with role="listitem" inside a <div role="presentation"> inside a <ul role="list"> still has the correct parent in the accessibility tree.

The aria-owns attribute can also rearrange parent-child relationships in the accessibility tree, making an element a child of another element regardless of DOM position. However, support for aria-owns varies across browsers and assistive technologies, so native DOM nesting is more reliable.

Common roles and their required parents

Here are some of the most frequently encountered required context roles from WAI-ARIA 1.2:

  • listitem requires list
  • tab requires tablist
  • row requires table, grid, rowgroup, or treegrid
  • cell requires row
  • gridcell requires row
  • columnheader requires row
  • rowheader requires row
  • option requires listbox or group
  • menuitem requires menu, menubar, or group
  • treeitem requires tree or group

How to fix it

There are two approaches:

  1. Wrap the element in a parent that has the required context role. If you have an element with role="listitem", make sure its parent (in the accessibility tree) has role="list".

  2. Use native HTML elements that provide the correct structure automatically. A <li> inside a <ul> already has the right implicit roles without any ARIA attributes. Native HTML is generally preferred because it has broader support and requires less manual work.

When the fix depends on restructuring the component's markup, the appropriate solution will vary by context.

Examples

Incorrect: listitem without a list parent

<div>
<div role="listitem">Apples</div>
<div role="listitem">Oranges</div>
</div>

The parent <div> has no role, so the listitem elements have no list context. A screen reader cannot tell the user that these items belong to a list or how many items the list contains.

Correct: listitem inside a list parent

<div role="list">
<div role="listitem">Apples</div>
<div role="listitem">Oranges</div>
</div>

Correct: using native HTML instead

<ul>
<li>Apples</li>
<li>Oranges</li>
</ul>

Native HTML is the simplest fix here. The <ul> implicitly has the list role, and each <li> implicitly has the listitem role.

Incorrect: tab without a tablist parent

<div>
<button role="tab" aria-selected="true">Details</button>
<button role="tab" aria-selected="false">Reviews</button>
</div>

The tab role requires a parent with role="tablist". Without it, screen readers cannot present these elements as navigable tabs.

Correct: tabs inside a tablist

<div role="tablist">
<button role="tab" aria-selected="true">Details</button>
<button role="tab" aria-selected="false">Reviews</button>
</div>

Incorrect: cells without a row parent

<div role="table">
<div role="cell">Name</div>
<div role="cell">Email</div>
</div>

Each cell must be a direct child of a row in the accessibility tree.

Correct: cells inside rows inside a table

<div role="table" aria-label="Contacts">
<div role="row">
<div role="cell">Name</div>
<div role="cell">Email</div>
</div>
</div>

Correct: presentation elements between parent and child in the DOM

<div role="list">
<div role="presentation">
<div role="listitem">Apples</div>
<div role="listitem">Oranges</div>
</div>
</div>

The intermediate <div> has role="presentation", which removes it from the accessibility tree. The listitem elements are still direct children of the list in the accessibility tree, so the required context is satisfied.

Detect accessibility issues automatically

Rocket Validator scans your site with complementary accessibility engines, helping teams find issues across every page.

Help us improve our guides

Was this guide helpful?
๐ŸŒ Trusted by teams worldwide

Validate at scale.
Ship accessible websites, faster.

Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.

Scheduled Reports
API Access
Open Source Standards
$7 / 7 days

Pro Trial

Full Pro access. Cancel anytime.

Start Pro Trial โ†’

Join teams across 40+ countries