The aria-allowed-attr rule flags an ARIA attribute on an element whose role does not support it – aria-selected on a plain <button>, aria-checked on a link. Browsers do not pass such a state on, so the information you meant to give never arrives. The fix is either the right role for the widget, or the attribute that role does support.
What the rule means
WAI-ARIA 1.2 defines, for every role, which states and properties it supports [3]. Global attributes such as aria-label, aria-describedby or aria-hidden work almost everywhere. Widget states do not: aria-selected belongs to tab, option, row, gridcell and a few more; aria-checked to checkbox, radio, switch and the checkable menu items; aria-pressed to button. The role that counts is the element's actual role – written in role, or the one HTML gives it: <button> is a button, <a href> is a link, <li> is a list item.
axe fails every attribute that is not in the role's list. It asks a person instead when the attribute is deprecated in ARIA 1.2, such as aria-grabbed or aria-dropeffect, and when it cannot be sure of the role of an unknown custom element.
Two related problems belong to other axe rules: a misspelled attribute name (aria-labeledby) and a name on an element that must not be named, such as aria-label on a plain <div>. aria-allowed-attr passes both.
Who is affected
Screen reader users are told the role and nothing more: "Reviews, button" instead of "Reviews, tab, selected, 2 of 3". They cannot tell which tab is active or which page of the navigation they are on. Voice control users may not be able to address the control by what it looks like. Everybody who relies on the accessibility tree gets less than the sighted mouse user sees.
Why the check fails
- Tabs made of plain buttons, with
aria-selectedon each button but norole="tab"orrole="tablist". - Navigation marking the current page with
aria-selected="true"on a link instead ofaria-current="page". - Toggle buttons using
aria-checkedwhere a button supportsaria-pressed. - Accordion or menu items with
aria-expandedon a<li>rather than on the button inside it. - A role removed or changed in a refactor while the attributes stayed.
- Copied snippets from an older ARIA version, with deprecated attributes like
aria-grabbed.
How to fix it
- Decide what the widget is: a set of tabs, a toggle, a navigation. Look up the pattern in the ARIA Authoring Practices Guide [5].
- Give each element the role that pattern names, so the attribute becomes valid.
- Or keep the element as it is and swap the attribute for one its role supports –
aria-pressedon a button,aria-currenton a link.
<!-- Before: plain buttons carrying a state only tabs support -->
<div class="tabs">
<button class="tabs__tab is-active" aria-selected="true">Specifications</button>
<button class="tabs__tab" aria-selected="false">Reviews</button>
</div>
<div class="tabs__panel" id="panel-specs"><p>Weight: 1.2 kg</p></div>
<!-- After: tab roles, so aria-selected is supported and announced -->
<div class="tabs" role="tablist" aria-label="Product details">
<button class="tabs__tab" role="tab" id="tab-specs" aria-selected="true"
aria-controls="panel-specs">Specifications</button>
<button class="tabs__tab" role="tab" id="tab-reviews" aria-selected="false"
aria-controls="panel-reviews" tabindex="-1">Reviews</button>
</div>
<div class="tabs__panel" role="tabpanel" id="panel-specs" aria-labelledby="tab-specs"><p>Weight: 1.2 kg</p></div>
<div class="tabs__panel" role="tabpanel" id="panel-reviews" aria-labelledby="tab-reviews" hidden><p>4.6 of 5</p></div>
The current page in a navigation needs no new role, only the attribute a link supports:
<!-- Before: links cannot be "selected" -->
<nav aria-label="Main"><a href="/shop/" aria-selected="true">Shop</a> <a href="/about/">About</a></nav>
<!-- After: aria-current is allowed on every element -->
<nav aria-label="Main"><a href="/shop/" aria-current="page">Shop</a> <a href="/about/">About</a></nav>
A role brings keyboard behaviour with it: tabs move with the arrow keys. Adding role="tab" without that behaviour fixes the rule and leaves the widget half built.
How to test it manually
- Select the element in your browser's developer tools and open the Accessibility pane: an unsupported attribute is not listed among the element's states.
- With a screen reader such as NVDA (free) or VoiceOver, move to the tabs or the navigation and listen for "selected" or "current page".
- For a widget that got a new role, check its keyboard pattern too – arrow keys for tabs, Space or Enter for toggles.
- What the rule cannot see: whether the role you chose is the right one for the widget.
Related WCAG criterion
4.1.2 Name, Role, Value, Level A: roles and states must be exposed correctly. A tab set that is not announced as one also loses structure covered by 1.3.1 Info and Relationships.
How Reviseberg reports it
Reviseberg runs aria-allowed-attr on every crawled page. The issue list shows the rule with its severity, WCAG 4.1.2 and Level A, the number of elements and pages, and the points a fix gets you back; the detail view shows the selector, the HTML snippet with the attribute and every affected page. Deprecated attributes and unclear roles go to the Potential issues queue for a person to decide; they cost nothing and are never counted as a pass. Findings can be marked "ignore", "can't fix" or "false positive" with a reason, and every decision is logged.