ARIA Role Must Be Appropriate for the Element: How to Fix It
- January 4, 2023
- Accessibility, ARIA

This check flags elements where an ARIA role contradicts the semantics the HTML tag already carries — slapping role="button" on an <a href>, or role="heading" on a <li>. When you override a native element with the wrong role, assistive tech announces one thing while the browser behaves like another, and keyboard support silently breaks.
Roles override semantics — that’s the danger
An ARIA role doesn’t add to an element’s meaning; it replaces it. The moment you write role="button" on a link, the accessibility tree stops treating it as a link. Screen readers announce “button,” users expect Space to activate it, and the underlying <a> still tries to navigate on click. You’ve created a control whose promise and behavior disagree. The first rule of ARIA is real: no ARIA beats bad ARIA, and a native element with a contradicting role is bad ARIA.
A real failing pattern and the fix
<!-- FAILING: link forced to masquerade as a button -->
<a href="/checkout" role="button">Checkout</a>
<!-- FAILING: list item pretending to be a heading -->
<li role="heading" aria-level="2">Shipping options</li>
<!-- FAILING: div given a role its element can't fulfil -->
<div role="textbox">Type here</div><!-- FIXED: use the element that already means what you want -->
<a href="/checkout" class="btn">Checkout</a>
<h2>Shipping options</h2>
<input type="text" aria-label="Type here">If a control genuinely needs button behavior — it runs JavaScript and never navigates — then use a real <button>. If it navigates to a URL, it’s a link; style it to look like a button, but leave the semantics alone. The element and the role should tell the same story.
Common mismatches and what to write instead
| Wrong pairing | What the user is promised | What actually happens | Correct approach |
|---|---|---|---|
<a role="button"> | Space activates, no navigation | Enter navigates, Space scrolls | Real <button> or drop the role |
<div role="link"> | Followable link | No focus, no keyboard, no href | <a href> |
<li role="heading"> | Landmark heading | Removed from its list context | <h2>–<h6> |
<button role="link"> | Navigation | Button still fires on Space | <a href> |
<table role="presentation"> with real data | Decoration | Column/row relationships stripped | Keep the table semantic |
How to detect it on your own site
- axe DevTools: run a scan and filter for “aria-allowed-role”. It fires on any element carrying a role that isn’t permitted for its tag, and gives you the exact node and the roles that are allowed.
- Lighthouse: the Accessibility category includes “ARIA roles used must conform to valid values” and “[role] values are not allowed for the given element” — both surface contradicting roles.
- WAVE: enable the extension and open the Details tab; ARIA roles show as icons on each element. Anywhere a role icon sits on an element whose native tag already implies a role, inspect it.
- Accessibility inspector: in the browser’s Accessibility pane, select the element and read its computed role. If it says “button” over an anchor, or “heading” over a list item, you’ve confirmed the mismatch.
How to fix it
- Start by asking what the control does: navigates → link, runs script in place → button, groups content → heading or region. Pick the native element that matches.
- Delete the redundant or contradicting
role. A<nav>already has rolenavigation; a<button>already has rolebutton. Repeating or overriding them adds risk, never value. - Where you truly must build a custom widget on a
<div>, you take on the whole contract: role,tabindex, keyboard handlers, and states. Half a contract is worse than none. - Never use
role="presentation"orrole="none"on elements carrying real semantic content — that strips meaning screen readers depend on. - Re-run axe until
aria-allowed-rolereports zero violations.
Why the wrong role costs you
A contradicting role is a quiet trap: your mouse test passes, so the bug ships. Then a keyboard user tabs to your fake “button” link, presses Space expecting activation, and the page scrolls instead. A screen-reader user is told “button” and never learns it will navigate them off the page. Roles also feed the accessibility tree that automated crawlers and AI agents read, so an honest role helps machines understand your interface as much as it helps people. When roles are right, the related requirement that every control also carry a matching accessible name that matches its visible text becomes far easier to satisfy.
FAQ
Is it ever fine to put a role on a native element?
Occasionally — for example role="tab" on a <button> inside a tablist, because that refines a compatible element. The failure is reserved for roles that contradict the element, like a link acting as a button or a div acting as a textbox.
Why not just add tabindex and keyboard handlers to my role="button" link?
You can, but you’re rebuilding what <button> gives you for free, and you must also stop the link from navigating. Every line of that is a chance to introduce a new bug. Use the native element.
Does role="presentation" count as a mismatch?
It does when applied to content that carries meaning — a data table, a heading, a list. Stripping their roles hides real structure from assistive tech. It’s only safe on purely decorative wrappers.
Will fixing roles change how my page looks?
No. Roles are semantic, not visual. Swap an <a role="button"> for a real <button> or link and apply the same CSS class — pixels are identical, semantics are honest.
How does this relate to toggle and tooltip roles?
Those are refinements you add to build a widget; this check is about roles that conflict with the base element. See ARIA toggle fields and ARIA tooltips for naming those widget roles correctly.
Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.
About SEO ProCheck
Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.
Work With Me
Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.







