About this AccessLint rule
Every HTML element carries built-in semantics that browsers and assistive technologies rely on. A <nav> element, for example, is automatically understood as a navigation landmark. A <button> is understood as an interactive control. When you add an ARIA role attribute that conflicts with or duplicates these built-in semantics, you create problems: assistive technology may announce the element incorrectly, ignore it, or present confusing information to the user.
This rule flags cases where an ARIA role is not appropriate for the element it's placed on. There are two common ways this happens:
- A role is added that conflicts with the element's native semantics (e.g.,
role="heading"on a<button>). This overrides the element's expected behavior and confuses screen reader users, who hear one type of control but encounter different interaction patterns. - A role is added that matches the element's implicit role (e.g.,
role="banner"on a<header>that is a direct child of<body>). This is redundant. While it usually doesn't break anything, it adds unnecessary noise to the code and can signal a misunderstanding of how HTML semantics work.
Screen reader users are the most directly affected. They depend on accurate role information to understand what an element is and how to interact with it. A <ul> with role="heading" would be announced as a heading, but it would not behave like one in heading navigation. Keyboard users can also be affected when roles imply interaction patterns that the element doesn't actually support.
Related WCAG success criteria
This rule relates to WCAG 4.1.2: Name, Role, Value (Level A). This criterion requires that the role of every user interface component can be programmatically determined. When an element's ARIA role contradicts its native semantics, the programmatically determined role becomes misleading, which is a failure of this criterion.
How to fix it
The fix depends on the situation:
If the role is redundant (matches the element's implicit role), remove the
roleattribute. The element already communicates the correct semantics without it.If the role conflicts with the element's native semantics, you have two options:
- Remove the
roleattribute and let the element use its native semantics. - Replace the element with one whose native semantics match the role you need. For example, if you need a heading, use an
<h1>–<h6>element instead of addingrole="heading"to a<div>that already has a different implicit role.
- Remove the
If you genuinely need to override an element's role, make sure the new role is in the list of allowed roles for that element. The ARIA in HTML specification defines which roles are permitted on each HTML element.
Examples
Redundant role on a landmark element
The <nav> element already has an implicit role of navigation. Adding it explicitly is unnecessary.
<!-- Before: redundant role -->
<nav role="navigation">
<a href="/home">Home</a>
<a href="/about">About</a>
</nav>
<!-- After: remove the redundant role -->
<nav>
<a href="/home">Home</a>
<a href="/about">About</a>
</nav>
Conflicting role on a semantic element
Placing role="heading" on a <button> overrides the button's native semantics. Screen reader users will hear "heading" instead of "button," and they will not know they can activate it.
<!-- Before: conflicting role -->
<button role="heading" aria-level="2">Submit form</button>
<!-- After: use the correct element for each purpose -->
<h2>Submit form</h2>
If the element actually needs to be a button, remove the role:
<button>Submit form</button>
Conflicting role on a list element
A <ul> has an implicit role of list. Assigning role="navigation" to it overrides the list semantics without providing proper landmark behavior.
<!-- Before: inappropriate role on a list -->
<ul role="navigation">
<li><a href="/home">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
<!-- After: wrap the list in a nav element -->
<nav>
<ul>
<li><a href="/home">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
Redundant role on a header element
A <header> element that is a direct child of <body> (or not nested inside <article>, <aside>, <main>, <nav>, or <section>) has an implicit role of banner.
<!-- Before: redundant role -->
<header role="banner">
<h1>My Website</h1>
</header>
<!-- After: remove the redundant role -->
<header>
<h1>My Website</h1>
</header>
Allowed role override on a generic element
A <div> has no implicit role, so many ARIA roles can be applied to it without conflict. This is a valid use of the role attribute.
<div role="alert">
Your changes have been saved.
</div>
When in doubt, check the ARIA in HTML specification to confirm whether a given role is allowed on the element you're using. Choosing the right HTML element for the job is almost always better than overriding semantics with ARIA.
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