Who it affects
Someone using a screen reader arrows across a star rating and hears the raw symbols, star star star star, or nothing. The 4 out of 5 the developer wrote is never spoken.
Someone using a screen reader on a browser that does honour it hears the label but with the element's real content hidden, which can swallow a whole paragraph of text.
Someone using voice control tries to say the label to reach the element and nothing responds, because it is not a control and has no usable name.
Broken versus fixed
Both examples are live and rendered in a sandboxed frame. The broken one is deliberately broken.
Looks right. A screen reader reads the characters: black star, black star, black star, black star, white star, 128 reviews. The aria-label on a plain span is ignored.
Announced: 4 out of 5 stars, image, 128 reviews. role="img" makes the span a single nameable thing, and the label replaces the symbols.
Show the markup behind both examples
<style>body{font-family:system-ui;padding:16px;margin:0}.row{display:flex;align-items:center;gap:10px}.stars{color:#d69e2e;font-size:22px;letter-spacing:2px}.n{color:#4a5568;font-size:14px}</style>
<div class="row">
<span class="stars" aria-label="4 out of 5 stars">★★★★☆</span>
<span class="n">128 reviews</span>
</div>
<style>body{font-family:system-ui;padding:16px;margin:0}.row{display:flex;align-items:center;gap:10px}.stars{color:#d69e2e;font-size:22px;letter-spacing:2px}.n{color:#4a5568;font-size:14px}</style>
<div class="row">
<span class="stars" role="img" aria-label="4 out of 5 stars">★★★★☆</span>
<span class="n">128 reviews</span>
</div>
Test it by hand in two minutes
- Search the page source for aria-label= and aria-labelledby=. For each hit, look at the element it is on.
- If the element is a div, span, p or similar with no role attribute, the label is prohibited and probably ignored.
- In Chrome DevTools, select the element and open the Accessibility pane. If the computed Name is empty or shows the raw text rather than your label, the browser has discarded it.
- Turn on VoiceOver (Cmd+F5) or NVDA and read through the area. You should hear the words you wrote, once, and not the raw symbols or a duplicate.
The fix
<span aria-label="4 out of 5 stars">★★★★☆</span>
<span role="img" aria-label="4 out of 5 stars">★★★★☆</span>
Give the element a role that can carry a name, or move the label to the control, heading or image it was meant for. For a rating made of symbols, role="img" with the rating as the label is the usual answer.
Label on a wrapper div around a field
<div aria-label="Postcode">
<input type="text" name="postcode">
</div>
<div>
<label for="postcode">Postcode</label>
<input id="postcode" type="text" name="postcode">
</div>
The input is the thing that needs a name. A visible label element is better than aria-label because sighted people see it too.
Label on a paragraph
<p aria-label="Summary">Your order will arrive on Thursday.</p>
<p>Your order will arrive on Thursday.</p>
A paragraph cannot be named and does not need one. If you want a heading, use a heading element above it.
Common mistakes
- Adding role="text" or role="generic" to make the scanner stop; neither allows a label.
- Adding role="presentation" to the element, which removes it from the accessibility tree along with its label.
- Moving the label to a title attribute, which is read inconsistently and not at all on touch.
- Wrapping the content in a button or link just so it can be named, when it is not interactive.
- Using role="img" on a span that contains real sentences, which hides every word except the label.
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 can see a naming attribute on an element whose role (or lack of one) prohibits it. It cannot tell what the label was supposed to describe, so decide the right role or target yourself. 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-allowed-attr
Every ARIA role comes with a short list of attributes it understands.
A
ARIA roles must be valid
aria-roles
The role attribute only accepts names from the ARIA list: dialog, button, tab, listbox and so on.
A
Elements with role="img" must have alternative text
role-img-alt
Adding role="img" to a div, span or any other element tells assistive technology to treat it as a single picture.
A
Form fields must have labels
label
Every input and textarea needs a label that is programmatically tied to it, not just sitting nearby.