ARIA attributes need a role that supports them
- Rule:
axe/aria-allowed-attr - Checks: Elements must only use supported ARIA attributes
- WCAG: 4.1.2
- Fix class:
mechanical: A fix needs no authored text or visual decision.
Who it affects
Section titled “Who it affects”- People who use a screen reader or a braille display, most of them blind.
How to fix it
Section titled “How to fix it”A state is on an element whose role does not have it, such as aria-checked or aria-selected on a <button>
Section titled “A state is on an element whose role does not have it, such as aria-checked or aria-selected on a <button>”Use the attribute the role defines, or the role the attribute belongs to. A toggle button takes aria-pressed; an on/off control takes role="switch" with aria-checked; a selected tab takes role="tab" with aria-selected.
<button type="button" aria-pressed="false">Bold</button>A plain <div> or <span> carries a widget state, such as aria-expanded or aria-valuenow
Section titled “A plain <div> or <span> carries a widget state, such as aria-expanded or aria-valuenow”Put the state on the control that changes it. For a section that opens and closes, that is the <button> that toggles it, with aria-expanded and aria-controls; an element with no role exposes none of these states.
<button type="button" aria-expanded="false" aria-controls="filters">Filters</button><div id="filters" hidden> <label><input type="checkbox" name="in-stock"> In stock only</label></div>A value has capital letters, such as aria-pressed="True"
Section titled “A value has capital letters, such as aria-pressed="True"”Write the value in lowercase, as ARIA defines it. axe treats these values as case-sensitive because not every browser and assistive technology accepts other cases. A template that prints a boolean from another language often writes True or False.
axe asks for review because the attribute is deprecated, such as aria-grabbed or aria-dropeffect
Section titled “axe asks for review because the attribute is deprecated, such as aria-grabbed or aria-dropeffect”Remove it, since ARIA deprecated these drag-and-drop attributes. Give drag and drop a keyboard and single-pointer alternative, such as move buttons, and say in text what dragging does.
Fixes that fail
Section titled “Fixes that fail”Adding a role only so the attribute is allowed
Section titled “Adding a role only so the attribute is allowed”A role tells screen reader users what the element is and how to operate it. role="checkbox" on something that does not behave like a checkbox gives them the wrong expectations.
Removing the attribute without moving the state anywhere
Section titled “Removing the attribute without moving the state anywhere”axe passes, but people lose the information, such as whether a section is open. Put the state on the element that has it.
In React
Section titled “In React”The part of the fix that differs in React, in its syntax. The rest of the guidance holds.
A component spreads its props onto a wrapper, so a state meant for the control lands on a <div>
Section titled “A component spreads its props onto a wrapper, so a state meant for the control lands on a <div>”Spread the remaining props onto the interactive element, not its wrapper, so aria-expanded, aria-pressed and the like reach the element whose role supports them.
function FilterToggle({ label, ...props }) { return ( <div className="toggle"> <button type="button" {...props}> {label} </button> </div> );}
function Filters() { return <FilterToggle label="Filters" aria-expanded={false} aria-controls="filter-panel" />;}More on the rule
Section titled “More on the rule”axe-core’s documentation of the rule
CORA’s fix guidance adapts content from accessibility-agents, under the MIT License: see its notice.