Why is my role="presentation" element still announced?
presentation-role-conflict page
The issue
An element marked presentational is meant to disappear from the accessibility tree, but one that can be focused, or that carries a global ARIA attribute, stays in it. Screen reader users then meet an element the author meant to hide, often with no name and no useful role.
The cause is a rule in the ARIA specification: when a presentational role conflicts with focusability or a global ARIA attribute, browsers ignore the presentational role. So role="presentation" on a table used for layout, with an aria-label left on it, keeps the table announced.
Scope
Each visible element with role="none" or role="presentation" is checked. It is a conflict if the element has a tabindex other than -1, or any global ARIA attribute other than aria-hidden, such as aria-label, aria-describedby, aria-live or aria-controls.
How to check you have it
- In probeo: the page reports the
presentation-role-conflictrule, “Elements with role none or presentation should not have global ARIA or tabindex”, with minor impact, saying whether the element has atabindex, global ARIA attributes, or both. This is a best practice rather than a WCAG criterion. - By hand: search the source for
role="presentation"androle="none", and look at the other attributes on each match. - With a tool: axe DevTools reports the same rule id. In the accessibility tree, a conflicted element still shows a role.
The fix
Decide whether the element is presentational, then remove whichever half contradicts that.
If it is layout only, remove the tabindex and the ARIA attributes. If it needs to be focused or named, it isn’t presentational: remove the role, and give it the role it actually plays.
<!-- Before -->
<table role="presentation" aria-label="Page layout">…</table>
<!-- After -->
<table role="presentation">…</table>Done when: no presentational element is focusable or carries global ARIA attributes, and the check above comes back clean.
Do not
- Do not use
role="presentation"to hide something that has to be focusable. - Do not use it as a substitute for
aria-hidden="true"; presentation removes the element’s role, not its content.
FAQ
What’s the difference between role=“none” and role=“presentation”?
None in effect. none was added as a clearer name for the same thing, and both are treated alike.
Does tabindex=“-1” cause a conflict?
Probeo doesn’t count it. tabindex="-1" keeps the element out of the tab order, though script can still focus it, so avoid it on presentational elements too.
Why isn’t aria-hidden a conflict?
aria-hidden removes the element and its content from the tree altogether, which agrees with a presentational role rather than contradicting it.
Which product detects this
Probeo checks this on every page of your site as part of Site Clarity. This page explains one instance; the product tells you every page that has it.