Skip to main content

Notes

Making Star Ratings and Review Widgets Accessible for E-Commerce Product Pages

Quietramp ·

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.

← Back to Notes