Making Star Ratings and Review Widgets Accessible for E-Commerce Product Pages
Quick answer: “Star ratings” on a product page are actually three separate accessibility
problems wearing the same five-star costume. The read-only average-rating display (★★★★☆ 4.2,
128 reviews) usually has no text alternative, failing WCAG SC 1.1.1 Non-Text Content. The
interactive “leave a review” star picker is usually a <div>-based hover widget with no
keyboard support and no accessible name for the value it holds, failing SC 4.1.2 Name, Role,
Value and SC 2.1.1 Keyboard. And the “Helpful / Not helpful” thumbs buttons under each review
are usually bare icons with no accessible name at all — a failure common enough on its own to
show up on 30.6% of home pages scanned, per the
WebAIM Million 2026 report.
Each has a specific, well-documented fix.
This article covers technical accessibility practice, not legal advice — it explains what WCAG 2.1 AA requires for rating and review widgets and how to implement it, not whether a specific site carries legal risk.
Why “fix the star rating” isn’t one task
Product pages and review sections put five-star iconography in three different places, and each one is a different kind of control with a different failure mode. Treating them as one design element — “the stars” — is exactly how all three end up unfixed at once: a developer patches the one that got flagged by a scanner and assumes the rest are covered because they look the same. They aren’t the same control, so they don’t share a fix.
1. The read-only average-rating display (SC 1.1.1 Non-Text Content)
The problem: the “4.2 out of 5, 128 reviews” summary near the top of a product page is
almost always built as five icon-font glyphs, a CSS-generated shape, or a sprite of <img>
elements — a purely visual representation with no text conveying the same information. A screen
reader either skips it entirely or, worse, reads it as a string of meaningless characters or
“graphic, graphic, graphic, graphic, graphic.”
WCAG SC 1.1.1 Non-Text Content (Level A) states its intent as making “information conveyed by non-text content… accessible through the use of a text alternative.” A star graphic conveying a rating value is exactly the case this criterion covers — the visual shape isn’t the information, the numeric rating it represents is.
The fix: W3C’s own WCAG 2.0 Technique ARIA10
documents this precise scenario, describing itself as showing “how to use the aria-labelledby
attribute to provide a short text description for a read-only complex graphic of a star rating
pattern; the graphic is composed of several image elements.” Its worked example:
<div role="img" aria-labelledby="star_id">
<img src="fullstar.png" alt="" />
<img src="fullstar.png" alt="" />
<img src="fullstar.png" alt="" />
<img src="fullstar.png" alt="" />
<img src="emptystar.png" alt="" />
</div>
<div id="star_id">4 of 5</div>
The individual star images carry empty alt="" (they’re decorative once the group has a name),
role="img" tells assistive technology to treat the whole row as one graphic, and
aria-labelledby points at a short, specific text alternative — the technique’s own example is
literally “4 of 5,” displayed visibly on the page beneath the star pattern rather than hidden.
Many sites already display “4.2 (128)” as visible copy right next to the stars for the same
reason — that works too, as long as it’s programmatically tied to the graphic. What SC 1.1.1
requires is that the information exists as text somewhere a screen reader can reach it; whether
that text is visible or visually hidden is a design choice, not a compliance requirement.
2. The interactive “leave a review” star picker (SC 4.1.2 and SC 2.1.1)
The problem: the star-picker input on a “write a review” form is a different control
entirely — it takes a value, not just displays one — and it’s usually built the same way product
swatches often are: a row of <div> or <span> elements styled with a hover-fill animation and
a click handler, with no keyboard support and no way for a screen reader to learn which rating
is currently selected.
WCAG SC 4.1.2 Name, Role, Value
(Level A) requires that a custom control’s name, role, and current value all “can be
programmatically determined,” with changes to that value exposed to assistive technology. A
mouse-only <div> widget satisfies none of it. It also fails
SC 2.1.1 Keyboard (Level A) on its
own terms, since a hover-triggered fill animation has no keyboard equivalent at all.
The fix: W3C’s WAI Tutorials page on Custom Controls
uses a star rating as its own worked example, and its recommended approach needs no custom ARIA
roles at all — it builds the picker from native radio inputs. In the tutorial’s own words: “a
form is used with its fields visually hidden. It contains six radio buttons, one for each star
and another for 0 stars, which is checked by default,” and “the labels for the radio buttons
contain actual text (‘1 Star,’ ‘2 Stars,’ …), and are also hidden visually” — so a screen reader
announces a real, specific label instead of an empty graphic. One detail that’s easy to miss: “the
form also contains a visually hidden submit button so that the form is not automatically submitted
when keyboard users browse through the radio buttons.” The star graphics are then styled on top of
the hidden native inputs using the :checked, :focus, and :hover CSS pseudo-classes — full
keyboard operability and correct value reporting come from the browser’s native radio-input
behavior, not custom JavaScript.
<fieldset>
<legend>Your rating</legend>
<input type="radio" id="star0" name="rating" value="0" checked />
<label for="star0" class="visually-hidden">0 Stars</label>
<input type="radio" id="star1" name="rating" value="1" />
<label for="star1" class="visually-hidden">1 Star</label>
<input type="radio" id="star2" name="rating" value="2" />
<label for="star2" class="visually-hidden">2 Stars</label>
<!-- 3, 4, 5 follow the same pattern -->
</fieldset>
This is a deliberately different pattern from a product page’s color/size variant swatches,
which typically need a custom ARIA radiogroup/radio treatment because the visual design
(a filled circle or square, not a checkbox-shaped star) doesn’t map onto a native input’s default
appearance as cleanly. A star picker doesn’t have that constraint — the star shape can be styled
directly from a native <input type="radio"> with CSS, so the simpler, native-HTML approach is
usually the better fit here specifically.
3. Icon-only “Helpful / Not helpful” buttons (SC 4.1.2 again)
The problem: the thumbs-up/thumbs-down controls under an individual review — used to vote a
review helpful or mark it unhelpful — are almost always rendered as a bare SVG or icon-font glyph
inside a <button> with no visible text and, very often, no aria-label either. This isn’t a
rating-widget-specific problem; it’s one of the more common accessibility failures on the web
generally. The WebAIM Million 2026 report found empty
buttons — buttons with no accessible text — on 30.6% of home pages scanned, up from 29.6%
the year before. That puts it behind the report’s most pervasive issues (low-contrast text at
83.9%, missing alt text at 53.1%, missing form labels at 51%, and empty links at 46.3%), but it
still shows up on close to a third of home pages — common enough that an icon-only
helpful/not-helpful button is a predictable, not edge-case, failure. A screen reader lands on
one and announces just “button,” with no indication of what clicking it does.
The fix: the same SC 4.1.2 Name, Role, Value requirement covered above applies directly — the
button needs a programmatically determinable name. The most reliable fix is an explicit
aria-label that states the action, not just the icon:
<button type="button" aria-label="Mark this review as helpful">
<svg aria-hidden="true" focusable="false"><!-- thumbs-up icon --></svg>
</button>
aria-hidden="true" on the icon itself keeps the SVG from being announced separately (some SVGs
are focusable or exposed by default in certain browser/AT combinations, which would otherwise
produce a duplicate or empty announcement alongside the button’s own label). If the button
toggles a helpful-vote count, that count update belongs in the same category as a cart-count
change — announce it via a live region rather than leaving it silent, the way “Cart updates that
are silent to screen readers” is covered in our
checkout and cart accessibility guide.
What a scanner catches here, and what still needs a person
Automated scanners catch the most literal version of each of these — an <img> with no alt
attribute, or a <button> with genuinely empty accessible-name computation, will usually surface
as a flagged violation. What they routinely miss: a star-picker whose radio inputs are hidden with
display: none instead of a proper visually-hidden technique, which removes them from the
accessibility tree entirely so the picker silently vanishes for screen-reader users while looking
fine to a sighted tester; an aria-label that exists but says something unhelpful like “button
icon” instead of the action; or a rating display whose aria-labelledby points at the wrong
element and announces stale text. Catching those requires operating the widget with a keyboard and
a screen reader and listening to what actually gets announced, not just confirming an
accessible-name attribute is present somewhere in the markup.
FAQ
Does the visible “4.2 (128 reviews)” text next to a star graphic count as the required text alternative? Yes, as long as it’s programmatically associated with the graphic or simply adjacent in the normal reading order, not sitting completely disconnected from it. A separate hidden label is often unnecessary once that visible text already exists.
Can I use the WAI-ARIA radio-group pattern instead of native radio inputs for the review-input
star picker?
Yes — the custom role="radiogroup"/role="radio" pattern (the same one used for product variant
swatches) works for a star-picker input too and is a reasonable choice if it fits an existing
component library better. The native-radio-input approach documented above is simply the one
W3C’s own tutorial uses for this exact widget, and it needs less custom ARIA to get right.
Is a hover-only fill animation on the star picker itself a WCAG violation? Not by itself — showing a preview fill on hover is a presentation detail. The violation is when hover is the only way to preview or set a value, with no keyboard equivalent. As long as keyboard focus and selection work through the underlying radio inputs, a hover effect on top is fine.
Get your review widgets checked by a person, not just a parser
Quietramp’s $890 audits include a manual pass through interactive widgets like star-rating inputs and review controls — checking accessible names, keyboard operability, and what a real screen reader announces, not just confirming that some markup exists. See a real sample report or check pricing.
This is educational content about technical accessibility practice, not legal advice. Meeting WCAG 2.1 AA does not constitute a legal compliance determination under the ADA or any other standard — consult qualified counsel for legal risk questions.
This article was drafted with AI assistance and reviewed by a person for accuracy before publication.