You're viewing the guides for Axe Core 4.11. A newer version is available — view the latest guides (Axe Core 4.12).
Accessibility Guides for mobility
Learn how to identify and fix common accessibility issues flagged by Axe Core — so your pages are inclusive and usable for everyone. Also check our HTML Validation Guides.
The accesskey attribute provides a keyboard shortcut that lets users quickly activate or move focus to a specific element, typically by pressing the designated key in combination with a modifier key (such as Alt on Windows or Control + Option on macOS). When multiple elements share the same accesskey value, browsers handle the conflict inconsistently — some will focus the first matching element, others will cycle through matches, and some may ignore the duplicates entirely. This unpredictability undermines the purpose of access keys and creates a confusing experience.
This issue primarily affects users who rely on the keyboard to navigate, including people who are blind and use screen readers, users with low vision who cannot easily track a mouse pointer, and users with motor disabilities who depend on keyboards or keyboard-emulating input devices. For these users, a duplicated access key can mean they can never reach the intended element, or they reach the wrong one without realizing it.
This rule is classified as a Deque Best Practice. While it doesn't map directly to a specific WCAG success criterion, it supports the broader principles behind WCAG 2.1.1 Keyboard (all functionality must be operable via keyboard) and WCAG 4.1.2 Name, Role, Value (user interface components must behave predictably). Duplicate access keys undermine keyboard operability by introducing unreliable shortcuts.
How to fix it
- Find all elements on the page that use the
accesskeyattribute. - Identify duplicates — any
accesskeyvalue that appears on more than one element. - Assign a unique value to each element so no two share the same key.
- Avoid conflicts with default browser and screen reader shortcuts. For example, many browsers reserve
Alt + Dfor the address bar andAlt + Ffor the File menu.
A note of caution about accesskey
While fixing duplicates is important, be aware that the accesskey attribute has significant limitations in practice:
- Inconsistent browser support: Not all browsers implement access keys the same way, and modifier key combinations vary across operating systems.
- Conflict risk: Developer-defined access keys can override default browser or assistive technology shortcuts, potentially breaking expected functionality.
- Discoverability: Access keys are invisible to most users unless explicitly documented on the page.
- Localization issues: A key that makes sense as a mnemonic in one language (e.g.,
sfor "Search") may not work in another.
For these reasons, many accessibility experts recommend avoiding accesskey altogether and instead relying on well-structured headings, landmarks, and skip links for efficient keyboard navigation.
Examples
Incorrect: duplicate accesskey values
Both links use accesskey="g", so the browser cannot determine which element to activate.
<a href="https://google.com" accesskey="g">Link to Google</a>
<a href="https://github.com" accesskey="g">Link to GitHub</a>
Correct: unique accesskey values
Each link has a distinct accesskey value, so keyboard shortcuts work as expected.
<a href="https://google.com" accesskey="g">Link to Google</a>
<a href="https://github.com" accesskey="h">Link to GitHub</a>
Correct: removing accesskey in favor of better patterns
If access keys aren't essential, consider removing them and providing clear navigation structure instead.
<nav aria-label="Main navigation">
<a href="https://google.com">Link to Google</a>
<a href="https://github.com">Link to GitHub</a>
</nav>
An image map is an <img> element linked to a <map> element via the usemap attribute. Inside the <map>, individual <area> elements define clickable hotspots that function as links. Each of these <area> elements is essentially a link, and like all links, it must have an accessible name that describes its purpose.
Why This Is an Accessibility Problem
Screen readers cannot interpret graphical content. When a user navigates to a clickable <area> that lacks alternative text, the screen reader has no meaningful label to announce. In many cases, it will fall back to reading the link URL or the image filename — neither of which conveys the purpose of the link. This critically impacts:
- Blind users and deafblind users who rely entirely on screen readers to navigate and interact with content.
- Users with mobility impairments who use assistive technologies like switch devices or voice control, which depend on accessible names to identify interactive elements.
This rule relates to the following WCAG success criteria:
- WCAG 2.4.4 – Link Purpose (In Context) (Level A): The purpose of each link must be determinable from the link text alone, or from the link text combined with its programmatically determined context. An
<area> without alternative text has no discernible purpose. - WCAG 4.1.2 – Name, Role, Value (Level A): All user interface components must have a programmatically determined name. An
<area> element is an interactive component, so it requires an accessible name.
This rule also applies under Section 508, EN 301 549, and Trusted Tester requirements.
How to Fix It
Ensure every active <area> element inside a <map> has an accessible name by using one of these methods:
alt attribute (preferred) — Add descriptive alt text directly to the <area> element.aria-label attribute — Provide a text label via aria-label.aria-labelledby attribute — Reference another element that contains the label text.
The alt text should clearly describe the purpose or destination of the link, not the visual appearance of the hotspot region.
Also, make sure the parent <img> element has its own alt attribute describing the image as a whole.
Examples
Incorrect: <area> Elements Without Alternative Text
In this example, the <area> elements have no alt text. Screen readers cannot communicate what each clickable region does.
<img src="solar_system.jpg" alt="Solar System" width="472" height="800" usemap="#solar-map">
<map name="solar-map">
<area shape="rect" coords="115,158,276,192" href="https://example.com/mercury">
<area shape="rect" coords="115,193,276,234" href="https://example.com/venus">
<area shape="rect" coords="115,235,276,280" href="https://example.com/earth">
</map>
Correct: <area> Elements With alt Text
Each <area> now has a descriptive alt attribute that communicates the link's purpose.
<img src="solar_system.jpg" alt="Solar System" width="472" height="800" usemap="#solar-map">
<map name="solar-map">
<area shape="rect" coords="115,158,276,192" href="https://example.com/mercury" alt="Mercury">
<area shape="rect" coords="115,193,276,234" href="https://example.com/venus" alt="Venus">
<area shape="rect" coords="115,235,276,280" href="https://example.com/earth" alt="Earth">
</map>
Correct: Using aria-label Instead of alt
<img src="floor_plan.png" alt="Office floor plan" width="600" height="400" usemap="#office-map">
<map name="office-map">
<area shape="rect" coords="0,0,200,200" href="/rooms/conference-a" aria-label="Conference Room A">
<area shape="rect" coords="200,0,400,200" href="/rooms/kitchen" aria-label="Kitchen">
</map>
Incorrect: Server-Side Image Map
Server-side image maps use the ismap attribute and rely on mouse click coordinates sent to the server. These are not keyboard accessible and provide no text alternatives for individual regions. Avoid this pattern entirely.
<a href="/maps/nav.map">
<img src="navbar.gif" alt="Navigation" ismap>
</a>
Instead, replace server-side image maps with client-side image maps (usemap and <map>) that include proper alt text on each <area>, or use a different navigational pattern altogether such as a standard list of links.
The WAI-ARIA specification defines a strict taxonomy of roles, states, and properties. Every role specifies exactly three categories of attributes it can use:
- Required attributes — must be present for the role to function correctly.
- Supported attributes — optionally enhance the role's semantics.
- Inherited attributes — come from superclass roles in the ARIA role hierarchy.
Any ARIA attribute that falls outside these three categories is not allowed on that role. This applies to both explicit roles (set via the role attribute) and implicit roles that HTML elements carry by default. For example, <button> has an implicit role of button, <input type="checkbox"> has an implicit role of checkbox, and <h2> has an implicit role of heading.
When an unsupported attribute appears on an element, the outcome is unpredictable. A screen reader might silently ignore it, or it might announce contradictory information — describing a heading as a checkable control, for instance. In the worst case, invalid role-attribute combinations can completely break accessibility for entire sections of a page.
Who is affected
This issue has a critical impact on people who rely on assistive technologies:
- Screen reader users (blind and deafblind users) depend on accurate role and state information to understand and interact with content. Conflicting ARIA attributes can cause elements to be announced as something they are not, creating confusion and preventing task completion.
- Voice control users rely on correctly exposed semantics to issue commands targeting specific controls. Misrepresented roles can make controls unreachable by voice.
- Users of switch devices and alternative input methods depend on tools that interpret ARIA roles and attributes to identify operable controls. Invalid attributes can make controls appear inoperable or misrepresent their purpose.
When ARIA attributes conflict with an element's role, these users may encounter controls that misrepresent their function, states that never update correctly, or regions that become entirely unusable.
Relevant WCAG success criteria
This rule relates to WCAG 2.0, 2.1, and 2.2 Success Criterion 4.1.2: Name, Role, Value (Level A), as well as EN 301 549 clause 9.4.1.2 and RGAA. This criterion requires that all user interface components expose their name, role, and value to assistive technologies in a way that can be programmatically determined. Using unsupported ARIA attributes on a role violates this criterion because it introduces properties that conflict with the element's actual role, breaking the contract between the page and assistive technology.
How to fix the problem
Identify the element's role. Check for an explicit role attribute. If none is present, determine the element's implicit ARIA role from its HTML tag. For example, <input type="checkbox"> has an implicit role of checkbox, and <nav> has an implicit role of navigation.
Look up the allowed attributes for that role in the WAI-ARIA specification's role definitions. Each role page lists its required states and properties, supported states and properties, and inherited properties from superclass roles.
Remove or relocate any ARIA attribute that isn't in the allowed list. If the attribute belongs on a different element within your component, move it there.
Reconsider the role. Sometimes the right fix isn't removing the attribute but changing the element's role to one that supports the attribute you need. For example, if you want a toggleable control, use role="switch" or role="checkbox" instead of role="button".
Consult the ARIA in HTML specification for additional conformance rules about which ARIA attributes are appropriate on specific HTML elements, including restrictions on how elements can be named.
Examples
Incorrect: unsupported attribute on an explicit role
The aria-checked attribute is not supported on role="textbox" because a textbox is not a checkable control. A screen reader might announce this element as both a text input and a checked control, confusing users.
<div role="textbox" aria-checked="true" contenteditable="true">
Enter your name
</div>
Correct: unsupported attribute removed
Remove aria-checked since it has no meaning on a textbox. Use aria-label to provide an accessible name.
<div role="textbox" contenteditable="true" aria-label="Your name">
</div>
Incorrect: unsupported attribute on an implicit role
The <h2> element has an implicit role of heading. The aria-selected attribute is not supported on headings because headings are not selectable items.
<h2 aria-selected="true">Account Settings</h2>
Correct: unsupported attribute removed from heading
If selection semantics aren't needed, simply remove the attribute. If you need selection behavior, use an element with an appropriate role such as tab.
<h2>Account Settings</h2>
Incorrect: role doesn't match the intended behavior
The developer wants a toggleable control but used role="button", which does not support aria-checked.
<div role="button" aria-checked="true" tabindex="0">
Dark mode
</div>
Correct: role changed to one that supports the attribute
Changing the role to switch makes aria-checked valid. The element remains keyboard-operable via tabindex="0".
<div role="switch" aria-checked="true" tabindex="0" aria-label="Dark mode">
Dark mode
</div>
Incorrect: unsupported attribute on a native HTML element
The <a> element has an implicit role of link. The aria-required attribute is not supported on links because links are not form fields that accept input.
<a href="/terms" aria-required="true">Terms of Service</a>
Correct: unsupported attribute removed from link
Remove aria-required from the link. If you need to indicate that agreeing to terms is mandatory, communicate that through a form control such as a checkbox.
<a href="/terms">Terms of Service</a>
Correct: supported attribute on a matching implicit role
The aria-expanded attribute is supported on the implicit button role, making this combination valid and useful for indicating the state of a collapsible menu.
<button aria-expanded="false" aria-controls="menu-list">
Menu
</button>
<ul id="menu-list" hidden>
<li><a href="/home">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
HTML elements come with built-in semantics — a <button> is inherently a button, a <ul> is inherently a list, and so on. When you assign a WAI-ARIA role to an element, you're overriding those built-in semantics and telling assistive technologies to treat the element differently. However, not all overrides make sense. Some combinations conflict with the element's native behavior, its expected interaction patterns, or the browser's internal handling of the element. For example, assigning role="button" to a <ul> element creates a contradiction: the browser still treats it as a list structurally, but screen readers announce it as a button, resulting in confusing and unpredictable behavior.
This issue primarily affects users who rely on screen readers and other assistive technologies. These tools depend on accurate role information to communicate what an element is, how it behaves, and how to interact with it. When role assignments conflict with the underlying HTML element, screen readers may announce the wrong type of control, skip content entirely, or present a user interface that doesn't match what sighted users see. Users who are blind, deafblind, or who use assistive technologies for mobility impairments are all affected.
While this rule is classified as a Deque best practice rather than a direct WCAG failure, it aligns with the principles behind WCAG 4.1.2 Name, Role, Value, which requires that user interface components expose their role correctly to assistive technologies. Mismatched roles undermine this requirement. At best, an invalid element-role combination has no effect; at worst, it can disable accessibility for entire sections of a page.
How to Fix
- Check the ARIA in HTML specification. The ARIA in HTML spec defines which
role values are allowed for each HTML element. Before assigning a role, verify that the combination is permitted. - Use the right element for the job. Often, the best fix is to use a native HTML element that already has the semantics you need, rather than overriding a different element with a
role. For example, use a <button> for button behavior instead of adding role="button" to a <div>. - Restructure when necessary. If you need a specific role, find an element that is allowed to carry it. This might mean changing your markup structure slightly.
- Don't use abstract roles. Roles like
widget, landmark, roletype, structure, and command are abstract and must never be used directly in content. They exist only as conceptual categories in the ARIA taxonomy.
Examples
Incorrect: Role not appropriate for the element
A <ul> element assigned role="button" — lists cannot be buttons:
<ul role="button">Name</ul>
A <button> element assigned role="heading" — buttons should not be headings:
<button role="heading" aria-level="2">Welcome</button>
In both cases, the assigned role conflicts with the element's native semantics and expected behavior, causing assistive technologies to report inaccurate information.
Correct: Role appropriate for the element
A <ul> element assigned role="menu" — this is an allowed role for <ul>, and the child elements use compatible roles:
<ul role="menu">
<li role="none">
<button role="menuitem">Start</button>
</li>
<li role="none">
<button role="menuitem">Stop</button>
</li>
</ul>
Here, role="menu" is a permitted override for <ul>, role="none" removes the <li> list-item semantics (which aren't meaningful in a menu context), and role="menuitem" is allowed on <button> elements.
Correct: Using native HTML elements instead of role overrides
Rather than forcing mismatched roles, use elements that already have the semantics you need:
<button type="button">Name</button>
<h2>Welcome</h2>
Native HTML elements provide built-in keyboard support, focus management, and correct semantics without any ARIA needed. This is almost always the simplest and most robust approach.
The aria-braillelabel and aria-brailleroledescription attributes were introduced to give authors fine-grained control over how content is presented on refreshable braille displays. For example, a visual "4 stars" rating might be represented as **** in braille to save space and improve readability on a limited-cell display. Similarly, a custom role description like "slide" might be abbreviated to "sld" for braille output.
However, these braille-specific attributes are designed as overrides, not standalone values. They modify how an existing accessible name or role description is rendered in braille. If no accessible name or role description exists, there's nothing for the braille attribute to override. The WAI-ARIA specification states that braille attributes without their non-braille equivalents should be ignored, but assistive technologies may not handle this consistently. Some screen readers might display the braille-only text while others ignore it entirely, leading to an unpredictable experience.
Who is affected
This issue primarily impacts users who are blind or deafblind and rely on refreshable braille displays. It can also affect users with mobility impairments who use assistive technologies that interpret ARIA attributes. When braille attributes lack their non-braille counterparts, these users may encounter missing labels or confusing role information, making it harder — or impossible — to understand and interact with content.
Related WCAG success criteria
This rule maps to WCAG Success Criterion 4.1.2: Name, Role, Value (Level A), which requires that all user interface components have an accessible name and role that can be programmatically determined. Using aria-braillelabel without a proper accessible name, or aria-brailleroledescription without aria-roledescription, means the element's name or role description is not reliably communicated to assistive technologies. This applies to WCAG 2.0, 2.1, and 2.2 at Level A, as well as EN 301 549 guideline 9.4.1.2.
How to fix it
- Add a non-braille equivalent. If an element has
aria-braillelabel, ensure it also has an accessible name — via aria-label, aria-labelledby, visible text content, or the alt attribute on images. If an element has aria-brailleroledescription, ensure it also has aria-roledescription. - Check attribute placement. The
aria-braillelabel or aria-brailleroledescription attribute might be on the wrong element. Verify it's on the same element that has the corresponding accessible name or role description. - Remove unnecessary braille attributes. If the braille attribute isn't serving a meaningful purpose (e.g., if the braille text would be the same as the accessible name), remove it entirely.
Examples
Incorrect: aria-braillelabel without an accessible name
The image has an empty alt attribute, so it has no accessible name. The aria-braillelabel has nothing to override.
<img alt="" aria-braillelabel="****" src="stars.jpg">
Correct: aria-braillelabel with an accessible name
The button has an accessible name from the image's alt text. The aria-braillelabel overrides how that name appears on a braille display.
<button aria-braillelabel="****">
<img alt="4 stars" src="stars.jpg">
</button>
Incorrect: aria-brailleroledescription without aria-roledescription
The element has a braille role description but no aria-roledescription to serve as the non-braille equivalent.
<div
role="article"
aria-labelledby="slideheading"
aria-brailleroledescription="sld">
<h1 id="slideheading">My vacation in Rome</h1>
</div>
Correct: aria-brailleroledescription with aria-roledescription
Both aria-roledescription and aria-brailleroledescription are present, so the braille display can use the abbreviated version while screen readers use the full role description.
<div
role="article"
aria-labelledby="slideheading"
aria-roledescription="slide"
aria-brailleroledescription="sld">
<h1 id="slideheading">My vacation in Rome</h1>
</div>
Incorrect: aria-braillelabel on the wrong element
The aria-braillelabel is on a <span> that has no accessible name, even though the parent button does.
<button aria-label="Close">
<span aria-braillelabel="cls">X</span>
</button>
Correct: aria-braillelabel on the element with the accessible name
The aria-braillelabel is placed on the same element that has aria-label.
<button aria-label="Close" aria-braillelabel="cls">
<span>X</span>
</button>
When you assign a role like link, button, or menuitem to an element, you are telling the browser and assistive technologies that this element is an interactive command. Screen readers rely on the accessible name of these elements to communicate their purpose to the user. If no accessible name exists, a screen reader might announce something like "button" or "link" with no additional context — leaving the user with no way to understand what the control does.
This issue primarily affects users who are blind or have low vision and rely on screen readers, but it also impacts users with mobility impairments who may use voice control software to activate elements by name. If there is no name, voice control users cannot target the element with a spoken command.
Related WCAG Success Criteria
This rule maps to WCAG Success Criterion 4.1.2: Name, Role, Value (Level A). This criterion requires that all user interface components have a name that can be programmatically determined. It applies across WCAG 2.0, 2.1, and 2.2, and is also referenced in EN 301 549 (9.4.1.2), Trusted Tester guidelines, and RGAA.
The Trusted Tester guidelines further specify that the purpose of each link or button must be determinable from some combination of its text, accessible name, accessible description, or programmatically determined context.
How to Fix It
Ensure that every element with role="link", role="button", or role="menuitem" has an accessible name through one of these methods:
- Inner text content — Place readable text inside the element.
aria-label attribute — Add a non-empty aria-label with a descriptive name.aria-labelledby attribute — Point to the id of another element that contains visible, non-empty text.title attribute — Use a title attribute as a fallback (though aria-label or visible text is preferred).
When possible, prefer using native HTML elements (<a>, <button>) over custom ARIA roles, as they come with built-in accessibility behaviors. If you must use ARIA roles, always make sure the accessible name is clear and describes the action or destination.
Examples
Incorrect: No accessible name
These elements will be flagged because screen readers cannot determine their purpose.
<!-- Empty element with no text or label -->
<div role="link"></div>
<!-- Empty aria-label provides no name -->
<div role="button" aria-label=""></div>
<!-- aria-labelledby points to a non-existent element -->
<div role="menuitem" aria-labelledby="nonexistent"></div>
<!-- aria-labelledby points to an empty element -->
<div role="link" aria-labelledby="empty-label"></div>
<div id="empty-label"></div>
Correct: Accessible name provided
Each of these elements has a discernible name that screen readers can announce.
<!-- Inner text content -->
<div role="link" tabindex="0">Visit our help center</div>
<!-- aria-label attribute -->
<div role="button" tabindex="0" aria-label="Close dialog"></div>
<!-- aria-labelledby pointing to visible text -->
<div role="menuitem" tabindex="0" aria-labelledby="menu-label">
<span id="menu-label">Save document</span>
</div>
<!-- Combination of aria-label and inner text -->
<div role="link" tabindex="0" aria-label="Learn more about pricing">
Learn more
</div>
<!-- title attribute as a fallback -->
<div role="button" tabindex="0" title="Submit form"></div>
Preferred: Use native HTML elements
Native elements handle naming and keyboard behavior automatically, reducing the chance of accessibility issues.
<a href="/help">Visit our help center</a>
<button type="button">Close dialog</button>
Note: When testing with RGAA, issues reported by this rule may need to be mapped to a different RGAA test, such as 6.2.1 for links.
When ARIA attributes are applied to elements where the specification says they should not be used, the result is unpredictable behavior across browsers and assistive technologies. Different browsers handle these conflicts inconsistently — some ignore the ARIA attribute, others override the native state, and still others pass both values through. This inconsistency means that a screen reader user on one browser may hear a completely different state than a screen reader user on another, creating a confusing and unreliable experience.
This rule relates to WCAG 2.0/2.1/2.2 Success Criterion 4.1.2: Name, Role, Value (Level A), which requires that for all user interface components, the name, role, and states can be programmatically determined. When ARIA attributes conflict with native semantics or are used outside their allowed context, the programmatically determined state becomes ambiguous or incorrect. Users affected include people who are blind or deafblind and rely on screen readers, as well as people with mobility disabilities who use alternative input devices that depend on accurate ARIA information.
There are two main scenarios this rule checks:
The aria-checked Attribute on Native Checkboxes
The aria-checked attribute should not be used on an <input type="checkbox"> element. Native HTML checkboxes already communicate their checked state to the browser's accessibility tree through the checked property. When you add aria-checked on top of this, you create two competing sources of truth. If the native checked state and the aria-checked value fall out of sync — which is easy to do — some assistive technologies will report the native state while others report the ARIA state. The user has no way to know which is correct.
How to fix it
You have two options:
- Remove
aria-checked and rely on the native checked attribute or property. If you need a "mixed" or indeterminate state, set the indeterminate property on the checkbox via JavaScript. - Replace the native checkbox with a custom element (e.g., a
<div> or <span>) that uses role="checkbox" along with aria-checked. When doing this, you must also ensure the element is keyboard accessible (focusable and togglable with Space) and has an accessible name.
Row-Specific Attributes Outside a treegrid
The attributes aria-posinset, aria-setsize, aria-expanded, and aria-level are only valid on a row (a <tr> element or an element with role="row") when that row is inside a treegrid. These attributes describe hierarchical tree relationships — position within a set, nesting level, and expandability — which are concepts that only make sense in a tree grid context. When used inside a plain <table> or grid, these attributes serve no function and may cause screen readers to announce confusing or nonsensical information.
How to fix it
Either remove the unsupported attributes from the rows, or change the parent container's role to treegrid if the data truly represents a hierarchical, expandable structure. If you switch to treegrid, make sure cells use role="gridcell" and that the keyboard interaction pattern matches what users expect from a tree grid (arrow key navigation for expanding/collapsing rows).
Examples
Bad example: aria-checked on a native checkbox
The aria-checked attribute conflicts with the native checkbox state.
<label>
<input type="checkbox" aria-checked="true">
I agree to make my website accessible
</label>
Good example: native checkbox without aria-checked
The browser communicates the checked state natively — no ARIA override needed.
<label>
<input type="checkbox" checked>
I agree to make my website accessible
</label>
Good example: custom checkbox using aria-checked
When building a custom checkbox, aria-checked is appropriate because there is no native checked state.
<div role="checkbox" aria-checked="true" tabindex="0" aria-label="I agree to make my website accessible">
✓ I agree to make my website accessible
</div>
Bad example: tree attributes on rows inside a plain table
The aria-level and aria-expanded attributes are not valid on rows inside a <table>.
<table>
<tr aria-level="1" aria-expanded="false">
<td>My Downloads</td>
</tr>
<tr aria-level="2">
<td>Documents</td>
</tr>
</table>
Good example: tree attributes on rows inside a treegrid
Changing the table's role to treegrid makes these attributes valid and meaningful.
<table role="treegrid">
<tr aria-level="1" aria-expanded="false">
<td role="gridcell">My Downloads</td>
</tr>
<tr aria-level="2" class="hidden">
<td role="gridcell">Documents</td>
</tr>
</table>
Good example: removing unsupported attributes from a plain table
If the data is not hierarchical, simply remove the tree-related attributes.
<table>
<tr>
<td>My Downloads</td>
</tr>
<tr>
<td>Documents</td>
</tr>
</table>
The WAI-ARIA specification evolves over time. As it matures, certain roles are deprecated because they were found to be redundant, poorly supported, or better served by other mechanisms. When you use a deprecated role, you're relying on semantics that assistive technologies are no longer expected to support. This means the role may be completely ignored, misinterpreted, or cause unexpected behavior.
Users most affected include:
- Blind and deafblind users who rely on screen readers to convey the purpose and structure of elements on a page.
- Users with mobility impairments who depend on assistive technologies that use ARIA roles for navigation and interaction.
When a screen reader encounters an element with a deprecated role, it may announce it generically (e.g., as a simple group or section) or skip the role announcement entirely. This strips away meaningful context that helps users understand the content structure and interact with it effectively.
Relevant WCAG Success Criteria
This rule relates to WCAG Success Criterion 4.1.2: Name, Role, Value (Level A). This criterion requires that for all user interface components, the name, role, and value can be programmatically determined and that changes to these are available to assistive technologies. Using a deprecated role means the role cannot be reliably determined, which violates this requirement.
This applies across WCAG 2.0, 2.1, and 2.2 at Level A, as well as EN 301 549 (guideline 9.4.1.2).
How to Fix It
- Identify deprecated roles in your codebase. The axe-core rule checks all elements with a
role attribute against the current WAI-ARIA specification. - Replace deprecated roles with supported alternatives. Currently, the primary deprecated role flagged is:
directory: Replace with list, tree, or section depending on the content structure. If the directory represents a flat list of items (like a table of contents), use list. If it represents a hierarchical, expandable structure, use tree. If it's a general grouping of related content, use section.
- Test with assistive technologies after making changes to confirm the new role conveys the intended meaning.
As the WAI-ARIA specification continues to evolve, additional roles may be deprecated in future versions. Keep your ARIA usage up to date by referencing the latest WAI-ARIA specification.
Examples
Incorrect: Using the Deprecated directory Role
<div role="directory">
<ul>
<li><a href="#section-1">Section 1</a></li>
<li><a href="#section-2">Section 2</a></li>
<li><a href="#section-3">Section 3</a></li>
</ul>
</div>
The directory role is deprecated. Assistive technologies may not recognize it, leaving users without useful semantic information about this element.
Correct: Using a Supported Role Instead
If the content is a simple list of links (such as a table of contents), use list or rely on the native <ul> semantics:
<nav aria-label="Table of contents">
<ul>
<li><a href="#section-1">Section 1</a></li>
<li><a href="#section-2">Section 2</a></li>
<li><a href="#section-3">Section 3</a></li>
</ul>
</nav>
In this example, the native <ul> element already provides the list role, and wrapping it in a <nav> with an aria-label gives assistive technology users clear context about its purpose.
Correct: Using tree for Hierarchical Content
If the content represents an expandable, nested structure, use the tree role with appropriate child roles:
<ul role="tree" aria-label="Site map">
<li role="treeitem" aria-expanded="true">
Section 1
<ul role="group">
<li role="treeitem">Subsection 1.1</li>
<li role="treeitem">Subsection 1.2</li>
</ul>
</li>
<li role="treeitem">Section 2</li>
</ul>
Correct: Using section for a General Content Grouping
If the deprecated directory role was used simply to group related content, a <section> element with an accessible name is a good replacement:
<section aria-label="Staff directory">
<ul>
<li>Alex Johnson — Engineering</li>
<li>Maria Garcia — Design</li>
<li>Sam Lee — Marketing</li>
</ul>
</section>
The key is to choose a replacement that accurately reflects the structure and purpose of the content, ensuring assistive technologies can convey it meaningfully to users.
When a dialog appears on screen, assistive technologies announce it to the user along with its accessible name. This name gives essential context — it tells the user what the dialog is about, such as "Confirm deletion" or "Sign in to your account." Without an accessible name, screen reader users hear that a dialog has opened but have no way to understand its purpose, which can be disorienting and make the interface difficult to use.
This issue primarily affects users who are blind or have low vision and rely on screen readers, as well as users with mobility impairments who navigate with assistive technology. It is flagged as a serious issue by the axe accessibility engine and aligns with Deque's accessibility best practices.
How to Fix It
Ensure every element with role="dialog" or role="alertdialog" has an accessible name using one of these methods:
aria-label — Provide a concise, descriptive name directly on the dialog element.aria-labelledby — Reference the id of a visible element (typically a heading) inside the dialog that serves as its title.title — Use the HTML title attribute as a fallback, though aria-label or aria-labelledby are preferred.
Whichever method you choose, make sure the name clearly describes the dialog's purpose. Avoid empty strings or references to elements that don't exist or have no text content.
Examples
Incorrect: Dialog with No Accessible Name
The dialog has no aria-label, aria-labelledby, or title, so screen readers cannot announce its purpose.
<div role="dialog">
<h2>Unsaved Changes</h2>
<p>You have unsaved changes. Do you want to save before leaving?</p>
<button>Save</button>
<button>Discard</button>
</div>
Incorrect: Empty aria-label
An empty aria-label provides no useful information to assistive technologies.
<div role="alertdialog" aria-label="">
<p>An error occurred while saving your file.</p>
<button>OK</button>
</div>
Incorrect: aria-labelledby Pointing to a Nonexistent or Empty Element
If the referenced element doesn't exist or contains no text, the dialog still has no accessible name.
<div role="dialog" aria-labelledby="dialog-title">
<p>Please confirm your selection.</p>
<button>Confirm</button>
</div>
<!-- No element with id="dialog-title" exists -->
<div role="dialog" aria-labelledby="dialog-title">
<span id="dialog-title"></span>
<p>Please confirm your selection.</p>
<button>Confirm</button>
</div>
Correct: Using aria-labelledby to Reference a Heading
The aria-labelledby attribute points to the dialog's visible heading, giving it a clear accessible name.
<div role="dialog" aria-labelledby="dialog-title">
<h2 id="dialog-title">Unsaved Changes</h2>
<p>You have unsaved changes. Do you want to save before leaving?</p>
<button>Save</button>
<button>Discard</button>
</div>
Correct: Using aria-label
The aria-label attribute provides a concise name directly on the dialog.
<div role="alertdialog" aria-label="File save error">
<p>An error occurred while saving your file. Please try again.</p>
<button>Retry</button>
<button>Cancel</button>
</div>
Correct: Using the title Attribute
The title attribute works as a fallback naming mechanism, though aria-label or aria-labelledby are generally preferred because title has inconsistent support across assistive technologies.
<div role="dialog" title="Export Settings">
<p>Choose a format for your export.</p>
<select>
<option>PDF</option>
<option>CSV</option>
</select>
<button>Export</button>
<button>Cancel</button>
</div>
The aria-hidden="true" attribute tells assistive technologies to ignore an element and all of its descendants. This is useful for hiding purely decorative content — such as icon fonts or redundant visuals — that would clutter the screen reader experience. However, a serious problem arises when focusable elements like links, buttons, form inputs, or elements with tabindex="0" exist inside an aria-hidden="true" container.
When this happens, keyboard users can still Tab to those elements, but screen readers won't announce them. The user lands on what feels like an invisible, unlabeled control. They have no way to know what the element is or what it does. This affects blind users, deafblind users, users with low vision who rely on screen readers, and mobility-impaired users who navigate exclusively by keyboard.
It's also important to understand that aria-hidden="false" on a descendant does not override aria-hidden="true" on an ancestor. Once a parent is hidden from the accessibility tree, all children remain hidden regardless of their own aria-hidden value. Any focusable children inside that subtree still create the same problem.
Related WCAG Success Criteria
This rule primarily relates to WCAG Success Criterion 4.1.2: Name, Role, Value (Level A). This criterion requires that for all user interface components, the name and role can be programmatically determined, and states, properties, and values can be programmatically set. A focusable element inside an aria-hidden="true" container violates this because its name and role are stripped from the accessibility API while it remains reachable via keyboard — making it impossible for assistive technologies to convey its purpose. This rule is flagged across WCAG 2.0, 2.1, and 2.2 at Level A, as well as in Trusted Tester, EN 301 549, and RGAA guidelines.
How to Fix It
There are several strategies to resolve this issue:
- Remove
aria-hidden="true" from elements that contain focusable children, if those children need to be interactive. - Remove focusable elements from inside the
aria-hidden="true" container if the entire section is truly meant to be hidden. - Make focusable elements unfocusable by adding
tabindex="-1" to links, buttons, or other interactive elements inside the hidden container. - Use the
disabled attribute on form controls (not aria-disabled, which does not actually prevent focus). - Hide elements with CSS using
display: none or visibility: hidden, which removes them from both the accessibility tree and the focus order simultaneously.
If you need to hide content from assistive technologies, ensure equivalent meaning and functionality is still available through other accessible means.
Examples
Incorrect: Focusable link inside aria-hidden="true"
The link is removed from the accessibility tree but still receives keyboard focus.
<div aria-hidden="true">
<a href="/home">Home</a>
</div>
Incorrect: Offscreen focusable link inside aria-hidden="true"
Moving a link offscreen does not remove it from the focus order.
<div aria-hidden="true">
<a href="/" style="position:absolute; top:-999em">Link</a>
</div>
Incorrect: Using aria-disabled instead of disabled
The aria-disabled attribute does not actually prevent the input from receiving focus.
<div aria-hidden="true">
<input aria-disabled="true" />
</div>
Incorrect: Element with tabindex="0" and aria-hidden="true"
Adding tabindex="0" makes a normally non-focusable element focusable, creating a conflict with aria-hidden="true".
<p tabindex="0" aria-hidden="true">Some descriptive text</p>
Incorrect: Trying to override aria-hidden on a descendant
Setting aria-hidden="false" on a child does not re-expose it when a parent has aria-hidden="true". The button remains hidden from assistive technologies but still receives focus.
<div aria-hidden="true">
<div aria-hidden="false">
<button>Submit</button>
</div>
</div>
Incorrect: Focusable <summary> inside aria-hidden="true"
The <summary> element is natively focusable.
<details aria-hidden="true">
<summary>More info</summary>
<p>Additional details here.</p>
</details>
Correct: Non-focusable content inside aria-hidden="true"
A paragraph with no interactive elements is safe to hide.
<p aria-hidden="true">Decorative description text</p>
Correct: Focusable elements hidden with CSS display: none
Using display: none removes the link from both the focus order and the accessibility tree.
<div aria-hidden="true">
<a href="/" style="display:none">Link</a>
</div>
Correct: Focusable elements made unfocusable with tabindex="-1"
Adding tabindex="-1" removes the button from the tab order.
<div aria-hidden="true">
<button tabindex="-1">Close</button>
</div>
Correct: Form input properly disabled with the disabled attribute
The disabled attribute prevents the input from receiving focus entirely.
<input disabled aria-hidden="true" />
Correct: Removing aria-hidden and keeping elements interactive
If the content needs to be focusable, simply don't hide it from assistive technologies.
<div>
<a href="/home">Home</a>
</div>
When you use ARIA roles to create custom input controls instead of native HTML elements, the browser no longer automatically associates a label with the control. Native <input>, <select>, and <textarea> elements support the <label> element through implicit wrapping or explicit for/id pairing, but custom <div> or <span> elements with ARIA roles do not. This means you must supply an accessible name through ARIA-specific mechanisms.
This rule applies to elements with any of the following ARIA input roles:
comboboxlistboxsearchboxsliderspinbuttontextbox
Who is affected
Without an accessible name, users who rely on screen readers (including blind and deafblind users) hear only the role of the element — for example, "textbox" — with no indication of what information to enter. Users with mobility impairments who navigate via voice control also depend on accessible names to target specific controls by speaking their labels. This creates a serious barrier to interaction.
Related WCAG success criteria
This rule maps to WCAG 2.0, 2.1, and 2.2 Success Criterion 4.1.2: Name, Role, Value (Level A). This criterion requires that all user interface components have a name that can be programmatically determined by assistive technologies. It is a Level A requirement, meaning it represents the minimum baseline of accessibility.
How to fix the problem
Because <label> elements do not work reliably with non-native elements like <div> or <span>, you need to use one of these approaches:
aria-label — Add a concise, descriptive label directly on the element.aria-labelledby — Point to the id of one or more visible elements that serve as the label.title — Use the title attribute as a last resort (it is less discoverable for sighted users).
Make sure the accessible name you provide is not empty or whitespace-only, and that any id referenced by aria-labelledby actually exists in the DOM.
Common mistakes
- Setting
aria-label to an empty or whitespace-only string (e.g., aria-label=" "). - Using
aria-labelledby with an id that doesn't exist on the page. - Wrapping a custom ARIA widget in a
<label> element, which does not provide a programmatic name for non-native elements in most browser/screen reader combinations. - Using
<label for="id"> to point to a <div> — the for attribute only works with native labelable elements like <input>, <select>, and <textarea>.
Examples
Incorrect: no accessible name on a combobox
The <div> has a combobox role but no label of any kind.
<div role="combobox">England</div>
Incorrect: aria-label is only whitespace
An empty or whitespace-only aria-label does not count as an accessible name.
<div aria-label=" " role="combobox">England</div>
Incorrect: aria-labelledby references a non-existent id
The referenced id must exist in the document; otherwise the accessible name resolves to empty.
<div role="listbox" aria-labelledby="color-label">
<div role="option">Orange</div>
</div>
<!-- No element with id="color-label" exists -->
Incorrect: <label> wrapping a non-native element
Implicit label association does not work for <div> elements with ARIA roles.
<label>
First name
<div role="textbox"></div>
</label>
Incorrect: explicit <label for> targeting a non-native element
The for attribute only creates a programmatic association with native labelable elements.
<label for="name-field">First name</label>
<div role="textbox" id="name-field"></div>
Correct: aria-label on a combobox
<div role="combobox" aria-label="Country">England</div>
Correct: aria-labelledby pointing to a visible label
<p id="color-label">Select a color:</p>
<div role="listbox" aria-labelledby="color-label">
<div role="option">Orange</div>
</div>
Correct: aria-labelledby on a searchbox
<p id="search-label">Search currency pairs:</p>
<div role="searchbox"
contenteditable="true"
aria-labelledby="search-label"></div>
Correct: aria-label on a slider
<div role="slider"
aria-label="Choose a value"
aria-valuemin="1"
aria-valuemax="7"
aria-valuenow="2"
tabindex="0"></div>
Correct: aria-label on a spinbutton
<div role="spinbutton"
aria-label="Enter quantity"
aria-valuemin="0"
aria-valuemax="10"
aria-valuenow="8"
tabindex="0"></div>
Correct: aria-labelledby on a textbox
<p id="name-label">First name</p>
<div role="textbox"
contenteditable="true"
aria-labelledby="name-label"></div>
When possible, prefer native HTML form controls (<input>, <select>, <textarea>) because they have built-in label support and keyboard behavior. Use custom ARIA input roles only when native elements cannot meet your design requirements, and always ensure those custom controls have an accessible name.
The meter role in ARIA represents a scalar measurement within a known range — think of a gauge showing a value like CPU temperature, password strength, or storage capacity. When a screen reader encounters an element with role="meter", it announces the element as a meter, but without an accessible name, it cannot convey what is being measured. The user hears something like "meter" with no context, which is effectively meaningless.
This issue primarily affects users who are blind or have low vision and rely on screen readers, as well as users with mobility impairments who may navigate via assistive technologies. It relates to WCAG 2.0/2.1/2.2 Success Criterion 1.1.1: Non-text Content (Level A), which requires that all non-text content has a text alternative that serves an equivalent purpose. A meter without a name fails to provide this text alternative.
How to Fix
Ensure every element with role="meter" has a clear, descriptive accessible name using one of these methods:
aria-label — Add descriptive text directly to the element.aria-labelledby — Reference another visible element that contains the label text. The referenced element must exist and contain non-empty text.title — Use the title attribute as a fallback naming method (though aria-label or aria-labelledby are generally preferred).
The name should clearly describe what the meter is measuring so users understand its purpose in context.
Examples
Incorrect: Meter with no accessible name
The following meter has no name at all. A screen reader will announce it as a meter but cannot tell the user what it measures.
<div role="meter" aria-valuemin="0" aria-valuemax="100" aria-valuenow="75"></div>
Incorrect: Empty aria-label
An empty aria-label is equivalent to having no name.
<div role="meter" aria-label="" aria-valuemin="0" aria-valuemax="100" aria-valuenow="75"></div>
Incorrect: aria-labelledby referencing a nonexistent or empty element
If the referenced element doesn't exist or has no text content, the meter still lacks an accessible name.
<div role="meter" aria-labelledby="nonexistent" aria-valuemin="0" aria-valuemax="100" aria-valuenow="75"></div>
<div role="meter" aria-labelledby="empty-label" aria-valuemin="0" aria-valuemax="100" aria-valuenow="75"></div>
<div id="empty-label"></div>
Correct: Using aria-label
<div role="meter" aria-label="Disk usage" aria-valuemin="0" aria-valuemax="100" aria-valuenow="75"></div>
Correct: Using aria-labelledby
<span id="meter-label">Battery level</span>
<div role="meter" aria-labelledby="meter-label" aria-valuemin="0" aria-valuemax="100" aria-valuenow="42"></div>
Correct: Using the title attribute
<div role="meter" title="Signal strength" aria-valuemin="0" aria-valuemax="5" aria-valuenow="3"></div>
Correct: Using the native <meter> element with a <label>
When possible, prefer the native HTML <meter> element, which has built-in semantics and can be associated with a <label>.
<label for="fuel">Fuel level</label>
<meter id="fuel" min="0" max="100" value="68">68%</meter>
When a progress bar lacks an accessible name, users who rely on assistive technologies have no way to distinguish it from other progress bars on the page or understand its purpose. Imagine a page with two progress bars—one for a file upload and one for a software installation. Without accessible names, a screen reader user would hear "progress bar" twice with no context for either. This issue primarily affects users who are blind or have low vision, as well as users with mobility impairments who may navigate using voice commands that reference element names.
This rule relates to WCAG Success Criterion 1.1.1: Non-text Content (Level A), which requires that all non-text content has a text alternative that serves the equivalent purpose. A progress bar is a non-text indicator of status, so it needs a text-based name to convey its meaning to assistive technology users. This criterion applies across WCAG 2.0, 2.1, and 2.2 at Level A, meaning it is a baseline requirement.
How to Fix
Ensure every element with role="progressbar" has a meaningful accessible name using one of these techniques:
aria-label — Provide a concise, descriptive label directly on the element.aria-labelledby — Reference the id of another element that contains visible label text.title — Use the title attribute as a fallback (though aria-label or aria-labelledby are preferred).
The name should clearly describe what process or task the progress bar represents, such as "File upload progress" or "Installation progress."
Examples
Failing: Progress bar with no accessible name
A progress bar with no labeling attributes is announced generically with no context.
<div role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
</div>
Failing: Empty aria-label
An empty aria-label provides no name, so the progress bar remains unlabeled.
<div role="progressbar" aria-label="" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">
</div>
Failing: aria-labelledby pointing to a nonexistent or empty element
If the referenced element doesn't exist or has no text content, the progress bar still has no accessible name.
<div role="progressbar" aria-labelledby="missing-id" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100">
</div>
<!-- Or referencing an empty element -->
<div role="progressbar" aria-labelledby="empty-label" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100">
</div>
<div id="empty-label"></div>
Passing: Using aria-label
<div role="progressbar" aria-label="File upload progress" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
</div>
A screen reader will announce something like: "File upload progress, progress bar, 50%."
Passing: Using aria-labelledby
<h3 id="upload-heading">Uploading resume.pdf</h3>
<div role="progressbar" aria-labelledby="upload-heading" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100">
</div>
This approach is especially useful when a visible heading or label already describes the progress bar, keeping the visual and accessible names in sync.
Passing: Using title
<div role="progressbar" title="Installation progress" aria-valuenow="90" aria-valuemin="0" aria-valuemax="100">
</div>
The title attribute works as a naming mechanism, but note that it may also produce a tooltip on hover. Prefer aria-label or aria-labelledby when possible for a more consistent experience across assistive technologies.
The WAI-ARIA specification defines which attributes are permitted, required, or prohibited for each role. When you use a prohibited attribute on a role, you're relying on a combination that assistive technologies are not designed to support. The result is that the information you intended to communicate — such as a label or description — may be silently dropped.
This creates a serious problem for users who depend on assistive technologies, including people who are blind, deafblind, or have mobility impairments. Screen readers might ignore the prohibited attribute, leaving the user without context. Some assistive technologies may attempt to compensate, leading to inconsistent or confusing behavior across different tools and browsers.
A common example is using aria-label on an element with role="presentation" or role="none". These roles explicitly tell assistive technologies to ignore the element's semantics, so labeling it with aria-label is contradictory. Similarly, text-level semantic roles like code, insertion, deletion, strong, emphasis, subscript, superscript, and paragraph prohibit aria-label and aria-labelledby because these roles represent inline text content that should not carry an accessible name separate from their text content.
Related WCAG success criteria
This rule relates to WCAG Success Criterion 4.1.2: Name, Role, Value (Level A), which requires that for all user interface components, the name, role, and states/properties can be programmatically determined. Using prohibited ARIA attributes violates this criterion because the intended name or state information cannot be reliably communicated to assistive technologies.
How to fix it
When axe flags a prohibited ARIA attribute, consider these approaches:
- Remove the prohibited attribute — If the information it conveys is not essential, simply remove it.
- Change the element's role — Switch to a role that permits the attribute you need. For instance, if you need
aria-label, don't use role="none". - Provide the information as visible text — Instead of relying on the prohibited attribute, include the information directly in the page content where all users can access it.
- Move the attribute to a different element — Place the attribute on a parent or child element that has a role supporting it.
Examples
Incorrect: aria-label on an element with role="presentation"
The presentation role tells assistive technologies to ignore the element. Adding aria-label contradicts this and will be ignored.
<div role="presentation" aria-label="Navigation section">
<a href="/home">Home</a>
<a href="/about">About</a>
</div>
Correct: Use a role that supports aria-label
If the element needs an accessible name, use a role that permits labeling, such as navigation.
<nav aria-label="Navigation section">
<a href="/home">Home</a>
<a href="/about">About</a>
</nav>
Incorrect: aria-label on a text-level semantic role
Roles like code, strong, emphasis, insertion, and deletion prohibit aria-label and aria-labelledby.
<span role="code" aria-label="JavaScript variable declaration">
const x = 10;
</span>
Correct: Use visible text instead
Provide context through surrounding text content rather than a prohibited attribute.
<p>
The following JavaScript variable declaration
<code>const x = 10;</code>
assigns the value 10 to x.
</p>
Incorrect: aria-labelledby on role="none"
<h2 id="section-title">Features</h2>
<table role="none" aria-labelledby="section-title">
<tr>
<td>Fast</td>
<td>Reliable</td>
</tr>
</table>
Correct: Remove the conflicting role or the prohibited attribute
If the table needs to be labeled, remove role="none" so it retains its native table semantics.
<h2 id="section-title">Features</h2>
<table aria-labelledby="section-title">
<tr>
<td>Fast</td>
<td>Reliable</td>
</tr>
</table>
If the table is truly presentational and doesn't need a label, remove the aria-labelledby attribute instead.
<table role="none">
<tr>
<td>Fast</td>
<td>Reliable</td>
</tr>
</table>
Why This Is an Accessibility Problem
ARIA roles describe what an element is and how it behaves. Many roles depend on specific state or property attributes to convey critical information about the element. For example, a checkbox role requires aria-checked so users know whether the checkbox is selected. Without it, a screen reader user hears "checkbox" but has no idea whether it's checked or unchecked.
This issue affects users who are blind, deafblind, or have mobility impairments and rely on assistive technologies to interact with web content. When required attributes are missing, these users lose essential context about the state of interactive widgets.
This rule relates to WCAG 2.0, 2.1, and 2.2 Success Criterion 4.1.2: Name, Role, Value (Level A), which requires that for all user interface components, the name, role, and states can be programmatically determined. Missing required ARIA attributes directly violate this criterion because the element's state cannot be communicated to assistive technologies.
How Required Attributes Work
Each ARIA role has a set of required states and properties defined in the WAI-ARIA specification. These attributes are essential for the role to function correctly. Some common examples:
Role Required Attribute(s) checkboxaria-checkedcomboboxaria-expanded, aria-controlsslideraria-valuenow, aria-valuemin, aria-valuemax (note: aria-valuemin and aria-valuemax have implicit defaults of 0 and 100)optionaria-selectedscrollbararia-controls, aria-valuenowseparator (focusable)aria-valuenowmeteraria-valuenowheadingaria-level
Some roles inherit requirements from ancestor roles. When a role inherits from multiple ancestors and one ancestor marks a property as supported while another marks it as required, the property becomes required on the inheriting role.
In some cases, default values defined in the specification satisfy the requirement automatically, so you may not always need to explicitly set every attribute. However, explicitly providing required attributes is the safest approach.
How to Fix the Problem
- Identify the ARIA
role on the element. - Look up the role in the WAI-ARIA Roles documentation to find its required states and properties.
- Add any missing required attributes with appropriate values.
- Ensure the attribute values are updated dynamically as the widget state changes (e.g., toggling
aria-checked between true and false when a checkbox is clicked).
Alternatively, consider whether a native HTML element could replace the custom ARIA widget. Native elements like <input type="checkbox">, <input type="range">, and <select> handle state management automatically without needing ARIA attributes.
Examples
Incorrect: Checkbox missing aria-checked
<div role="checkbox" tabindex="0">
Accept terms and conditions
</div>
A screen reader announces this as a checkbox, but the user has no way to know if it is checked or unchecked.
Correct: Checkbox with aria-checked
<div role="checkbox" tabindex="0" aria-checked="false">
Accept terms and conditions
</div>
Better: Use a native HTML checkbox
<label>
<input type="checkbox">
Accept terms and conditions
</label>
Incorrect: Slider missing required value attributes
<div role="slider" tabindex="0">
Volume
</div>
Without aria-valuenow, assistive technologies cannot report the current value of the slider.
Correct: Slider with required attributes
<div role="slider" tabindex="0"
aria-valuenow="50"
aria-valuemin="0"
aria-valuemax="100"
aria-label="Volume">
</div>
Incorrect: Combobox missing aria-expanded and aria-controls
<input role="combobox" type="text" aria-label="Search">
Correct: Combobox with required attributes
<input role="combobox" type="text"
aria-label="Search"
aria-expanded="false"
aria-controls="search-listbox">
<ul id="search-listbox" role="listbox" hidden>
<li role="option">Option 1</li>
<li role="option">Option 2</li>
</ul>
Incorrect: Heading missing aria-level
<div role="heading">Section Title</div>
Correct: Heading with aria-level
<div role="heading" aria-level="2">Section Title</div>
Better: Use a native heading element
<h2>Section Title</h2>
The WAI-ARIA specification defines a strict hierarchy for many roles, where parent and child relationships must be maintained for the accessibility semantics to work as intended. For example, an element with role="list" must contain elements with role="listitem", just as a role="menu" must contain role="menuitem" (or related menu item roles). When these required child roles are absent, assistive technologies like screen readers cannot properly convey the structure of the component. A screen reader user navigating a tree view, for instance, needs to understand the parent container, individual items, and sibling relationships — none of which are communicated correctly if the expected child roles are missing.
This issue critically affects users who are blind, deafblind, or have mobility impairments and rely on assistive technologies to navigate and interact with complex widgets. Without the correct role hierarchy, these users may not understand what type of content they're interacting with, how many items exist, or how to navigate between them.
This rule relates to WCAG 2.0/2.1/2.2 Success Criterion 1.3.1: Info and Relationships (Level A), which requires that information, structure, and relationships conveyed through presentation can be programmatically determined. When ARIA roles lack their required children, the structural relationships are broken and cannot be programmatically determined by assistive technologies.
There are two ways the required parent-child relationship can be established:
- DOM structure: The child elements with the required roles are direct descendants (or appropriate descendants) of the parent element in the DOM.
aria-owns: When the DOM hierarchy doesn't match the intended accessibility tree structure, the aria-owns attribute can be used on the parent to explicitly associate child elements that exist elsewhere in the DOM.
How to Fix
- Identify the ARIA role on the parent element.
- Consult the WAI-ARIA specification to determine which child roles are required for that parent role.
- Ensure all direct children (or owned children via
aria-owns) have the correct required roles. - If you cannot add the required child roles, consider whether the parent role is appropriate for your use case, or use native HTML elements that provide these semantics automatically.
Common Parent-Child Role Requirements
Parent Role Required Child Role(s) listlistitemmenumenuitem, menuitemcheckbox, or menuitemradiomenubarmenuitem, menuitemcheckbox, or menuitemradiotablisttabtreetreeitem or groupgridrow or rowgrouptablerow or rowgrouprowcell, columnheader, gridcell, or rowheaderfeedarticle
Examples
Incorrect: Missing required child roles
This tablist has children that lack the required tab role:
<div role="tablist">
<div>Tab 1</div>
<div>Tab 2</div>
<div>Tab 3</div>
</div>
This list contains <div> elements without the listitem role:
<div role="list">
<div>Apple</div>
<div>Banana</div>
<div>Cherry</div>
</div>
This