Who it affects
Someone using a screen reader jumps through the landmarks on a checkout page and finds an unnamed region, because the heading was wired up with aria-labeledby.
Someone using a braille display reads the region with no label, and has no visual layout to fall back on.
The developer who wrote it is sure the label is there, because it is right there in the source, and cannot see why the screen reader disagrees.
Broken versus fixed
Both examples are live and rendered in a sandboxed frame. The broken one is deliberately broken.
Looks complete. The attribute is misspelt (one l), so the section has no name, is not a region landmark, and a screen reader's landmark list does not include Billing address at all.
Announced when entering it: Billing address, region. It now appears in the landmark list, so someone can jump straight to it.
Show the markup behind both examples
<style>body{font-family:system-ui;padding:16px;margin:0;font-size:14px}section{border:1px solid #cbd5e0;border-radius:8px;padding:12px 14px;width:280px}h2{margin:0 0 10px;font-size:16px}label{display:block;margin:6px 0 2px;color:#4a5568}input{width:100%;box-sizing:border-box;padding:5px}</style>
<section aria-labeledby="bill">
<h2 id="bill">Billing address</h2>
<label for="a1">Address line 1</label>
<input id="a1">
<label for="pc">Postcode</label>
<input id="pc">
</section>
<style>body{font-family:system-ui;padding:16px;margin:0;font-size:14px}section{border:1px solid #cbd5e0;border-radius:8px;padding:12px 14px;width:280px}h2{margin:0 0 10px;font-size:16px}label{display:block;margin:6px 0 2px;color:#4a5568}input{width:100%;box-sizing:border-box;padding:5px}</style>
<section aria-labelledby="bill">
<h2 id="bill">Billing address</h2>
<label for="a1">Address line 1</label>
<input id="a1">
<label for="pc">Postcode</label>
<input id="pc">
</section>
Test it by hand in two minutes
- Search the page source for aria- and read each attribute name slowly. The usual typos are aria-labeledby, aria-describeby, aria-labelled-by, aria-hiddden and aria-role.
- In Chrome DevTools, select the element and open the Accessibility pane. A misspelt attribute will not show up in the computed properties at all.
- Turn on VoiceOver (Cmd+F5) or NVDA and check the thing the attribute was meant to provide (a name, a description, a hidden element) is actually happening.
- If your editor has an HTML linter, turn on its ARIA checks; most will underline unknown aria- names as you type.
The fix
<section aria-labeledby="bill">
<section aria-labelledby="bill">
Correct the spelling to the real attribute. ARIA uses the double l British spelling in aria-labelledby, which trips up a lot of people; aria-describedby has one d before the by.
Description typo
<input id="pw" aria-describeby="pw-hint">
<input id="pw" aria-describedby="pw-hint">
Three syllables: described-by.
Invented attribute
<button aria-tooltip="Save your changes">Save</button>
<button aria-describedby="save-tip">Save</button>
<div role="tooltip" id="save-tip">Save your changes</div>
There is no aria-tooltip attribute. Use a tooltip element and reference it with aria-describedby.
Common mistakes
- Spelling aria-labelledby the American way, aria-labeledby.
- Writing aria-role instead of role, or aria-tabindex instead of tabindex.
- Inventing attributes that sound plausible, like aria-tooltip, aria-title or aria-active.
- Adding data- attributes with an aria- prefix for your own scripts, which the scanner reads as ARIA.
- Fixing the spelling in one component and leaving the same typo in the copy of it.
WCAG criteria this rule maps to
axe-core tags this rule as WCAG 2.2 level A. It is one of the checks for:
- 4.1.2 Name, Role, Value (level A). Official W3C text.
The scanner checks every attribute that starts with aria- against the list of real ARIA attributes, so typos are caught every time. It cannot guess which attribute you meant, so read the context and pick the right one. Automated tools find only part of the accessibility problems on a page; a pass on this rule is not a pass on the criterion.
Related rules
aria-valid-attr-value
Each ARIA attribute accepts a particular kind of value: true or false, a number, a word from a short list, or the id of another element.
A
ARIA attributes must be allowed for the element's role
aria-allowed-attr
Every ARIA role comes with a short list of attributes it understands.
A
aria-label must not be used on div, span or p without a role
aria-prohibited-attr
aria-label and aria-labelledby only work on elements that can have a name: controls, landmarks, images, headings, tables and similar.