Who it affects
Someone reading restaurant reviews with a screen reader reaches a star rating built from five span elements with role="img" and hears image, five times, never the score.
Someone with low vision using a screen reader alongside high zoom cannot make out a CSS background illustration and gets no spoken alternative to fall back on.
Someone using a braille display sees a blank graphic marker where a chart drawn with CSS should have been summarised in a sentence.
Broken versus fixed
Both examples are live and rendered in a sandboxed frame. The broken one is deliberately broken.
A screen reader reads: image. Some will read the raw star characters, black star black star black star black star white star, which is a puzzle rather than a score.
Announced: Rated 4 out of 5 stars, image. One phrase, same meaning as the picture.
Show the markup behind both examples
<style>body{font-family:system-ui;padding:16px;margin:0}.row{display:flex;gap:12px;align-items:center}.stars{color:#e0a100;font-size:26px;letter-spacing:2px}</style>
<div class="row">
<strong>The Copper Kettle, Harrogate</strong>
<span class="stars" role="img">★★★★☆</span>
</div>
<p>Lovely scones, slow service on a Saturday.</p>
<style>body{font-family:system-ui;padding:16px;margin:0}.row{display:flex;gap:12px;align-items:center}.stars{color:#e0a100;font-size:26px;letter-spacing:2px}</style>
<div class="row">
<strong>The Copper Kettle, Harrogate</strong>
<span class="stars" role="img" aria-label="Rated 4 out of 5 stars">★★★★☆</span>
</div>
<p>Lovely scones, slow service on a Saturday.</p>
Test it by hand in two minutes
- Open DevTools (F12), press Cmd+F or Ctrl+F in the Elements panel and search for role="img". Check each match has an aria-label, or an aria-labelledby that points at real text.
- Turn on VoiceOver (Cmd+F5) or NVDA and move through the page with the arrow keys. Each role="img" element should be announced as a short description followed by image.
- For a rating, chart or icon, ask whether the spoken words give the same information as the picture. Four stars should become something like 4 out of 5, not just stars.
- If the element is purely decorative, confirm it is skipped entirely rather than announced as image.
The fix
<span role="img" class="stars">★★★★☆</span>
<span role="img" class="stars" aria-label="Rated 4 out of 5 stars">★★★★☆</span>
Put the meaning in aria-label, not a description of the glyphs. If the text already exists on the page, point at it with aria-labelledby instead of repeating it.
CSS background image that carries meaning
<div role="img" class="map-pin"></div>
<div role="img" class="map-pin" aria-label="Entrance on Market Street"></div>
A background image has nowhere to put alt. role="img" plus aria-label is the right pair for it.
Decorative flourish
<span role="img" class="divider"></span>
<span class="divider" aria-hidden="true"></span>
If it adds nothing, drop the role and hide it. Do not give decoration an empty aria-label and leave the role in place.
Group of emoji
<span role="img">🏠🚀</span>
<span role="img" aria-label="Home and rocket emoji">🏠🚀</span>
Wrapping several emoji in one role="img" with a label stops each one being read separately.
Common mistakes
- Adding role="img" to make an icon font announce properly, then forgetting the aria-label that was the point of it.
- Writing aria-label="stars" or aria-label="icon", which names the picture type instead of its meaning.
- Using alt on a span or div; alt only works on img, area and input elements.
- Pointing aria-labelledby at an id that does not exist or at an empty element.
- Giving a decorative element role="img" with an empty label instead of aria-hidden="true".
WCAG criteria this rule maps to
axe-core tags this rule as WCAG 2.2 level A. It is one of the checks for:
- 1.1.1 Non-text Content (level A). Official W3C text.
The scanner can see that an element with role="img" has no aria-label, no aria-labelledby that resolves to text, and no title. It cannot judge whether the label matches what the picture means. 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
image-alt
Every img element needs an alt attribute.
A
SVG graphics with an image role must have alternative text
svg-img-alt
Inline SVG is drawn with code rather than loaded as a file, so there is no alt attribute to fill in.
A
Embedded objects must have alternative text
object-alt
The object element embeds another file in the page: a PDF timetable, an SVG, an audio file, sometimes a whole page.
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.