Source Code

<section class="srb-wrap">
  <span class="srb-tag">seller reputation</span>
  <h1>Northgate Camera Co.</h1>

  <div class="srb-summary">
    <span class="srb-avg" id="srbAvg">0.0</span>
    <div class="srb-summary-right">
      <div class="srb-stars" id="srbStars"></div>
      <div class="srb-count" id="srbCount">0 reviews</div>
    </div>
  </div>

  <div class="srb-bars" id="srbBars"></div>
</section>

Seller Rating Breakdown — Free Star Percentage Bar Chart

Seller Rating Breakdown · Charts · Plain HTML, CSS & JS · Live preview

What's included

Features

Single source dataset
reviewCounts drives every displayed number.
Weighted-average calculation
Sum(count × star) / total, not hardcoded.
Derived bar percentages
count / total × 100 per star level.
Consistent by construction
Average and bars can never contradict each other.
Rounded star glyphs
Visual stars round the precise average for display only.
Animated bar fills
Widths transition smoothly on render.
Locale-formatted totals
toLocaleString() for large review counts.
Framework-portable logic
computeStats() is pure and easy to reuse.

About this UI Snippet

Seller Rating Breakdown — Percentages Computed, Never Hardcoded

Screenshot of the Seller Rating Breakdown snippet rendered live

This snippet is the rating summary you see on any marketplace seller or product page — a big average score, a star row, a total review count, and a horizontal bar for each star level showing what share of reviews landed there. What makes it worth reusing is that every number on screen is *derived*, not typed in separately.

One dataset, every number derived from it

The entire component is driven by a single object: reviewCounts = { 5: 820, 4: 210, 3: 60, 2: 25, 1: 15 } — raw counts of how many reviews landed at each star level. computeStats() sums those counts for the total, and computes a weighted average as (5×820 + 4×210 + 3×60 + 2×25 + 1×15) / total. Change any single count in that object and the average, the total, the star-row rounding, and every bar's width and percentage label all update consistently, because none of them are stored independently — they're all recalculated from the same source.

Why that matters

A common shortcut is to hand-write percentage widths per bar (width: 82%, width: 12%...) that happen to look right for one dataset but silently go stale — or never actually summed to 100% in the first place — the moment the underlying numbers change. Here, percentage = count / total * 100 is computed per star level directly from the same counts used for the average, so the bars and the average can never contradict each other.

Rounding for the star row

The top-line star row rounds the average to the nearest whole star (Math.round(average)) purely for the filled/unfilled glyph display — the *numeric* average shown beside it (4.6) keeps full precision, so the visual shorthand never overstates what the exact number says.

Reusable with any dataset

Swap in your own reviewCounts object — pulled from an API response, a CMS field, or computed server-side — and every part of the UI recalculates correctly with no other code changes needed. Pair this with a rating breakdown or star rating input for a full reviews section, or a review form to collect the underlying data this component visualizes.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain why deriving the average and every bar's percentage from the same reviewCounts object guarantees they can never contradict each other, versus a version that hardcodes an average number and bar widths separately. It's also useful for reasoning about the star-rounding decision — ask why the numeric average keeps full precision while the star icon row rounds to the nearest whole star, and what UX problem that avoids. For extensions, ask it to add a filter that re-renders the review list below the summary when a specific star-level bar is clicked, or to animate the average number counting up from 0 on load. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "seller rating breakdown" summary in plain HTML, CSS, and JavaScript — no libraries.

Requirements:
- A single JS data object reviewCounts = { 5: <count>, 4: <count>, 3: <count>, 2: <count>, 1: <count> } representing raw review counts per star level (use realistic sample numbers like 820/210/60/25/15).
- CRITICAL: compute the overall average rating as a count-weighted mean directly from reviewCounts (sum of count × star level, divided by total review count) — do not hardcode the average as a separate number.
- CRITICAL: for each of the 5 star levels, render a horizontal bar whose width AND percentage label are both computed live as (countForThatLevel / totalReviews) * 100 — do not hardcode any bar's width or percentage.
- Display the computed average prominently (one decimal place), a 5-star icon row where whole stars are filled up to Math.round(average) while the numeric average text keeps full precision, and the total review count formatted with locale thousands separators.
- Bars should render 5-star at the top down to 1-star at the bottom, each showing the star level, a track/fill bar, and the percentage.
- Keep the calculation logic (computeStats or similar) as a pure function separate from the DOM-rendering code, so it's easy to port to a component framework.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSThe summary renders from the sample reviewCounts data.
  2. 2
    Check the averageComputed as a count-weighted mean, not typed in directly.
  3. 3
    Check each barWidth and percentage both equal count / total × 100.
  4. 4
    Edit reviewCountsChange any star's count and every number updates together.
  5. 5
    Confirm bars sum to 100%Because they share one source of truth, they always will.
  6. 6
    Swap in real API dataReplace the object with a fetched review-count response.

Real-world uses

Common Use Cases

Marketplace seller pages
The classic eBay/Etsy-style reputation summary.
Product review sections
Pair with rating breakdown.
App store listings
Show a star distribution for an app's reviews.
Restaurant/service platforms
Summarize customer feedback distribution.
Review collection flows
Follow up a review form with this summary.
B2B vendor scorecards
Adapt star levels to a different rating scale.
Related: Waffle Chart
See the Waffle Chart for a related charts pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

It's a count-weighted mean over the raw reviewCounts dataset: each star level's count is multiplied by its star value, those products are summed, and the total is divided by the overall review count — (5×countFor5 + 4×countFor4 + ... ) / totalReviews. It is never a separately hardcoded number, so it always matches whatever the underlying counts say.

Each star level's bar width and label both come from the same formula: percentage = (countForThatStar / totalReviews) * 100, computed live from the reviewCounts object in renderBars(). Because every bar uses the same total, the five percentages will always sum to 100% (aside from floating-point display rounding).

Individual star glyphs can only be visually filled or unfilled — there's no meaningful way to render "4.6 out of 5 stars" as partial icons in this simple version — so Math.round(average) picks the nearest whole number purely for that display. The numeric average text next to it keeps full one-decimal precision, so the visual shorthand never misrepresents the exact figure.

Yes — generalize the loop bounds in computeStats(), renderStars(), and renderBars() from a fixed 1-5 range to however many levels your scale uses, and adjust the reviewCounts keys to match. The weighted-average and percentage formulas themselves don't assume a 5-star scale specifically.

Move reviewCounts into a prop or fetched state value, call the same computeStats() logic (kept as a pure function) inside a derived/computed value, and map over the five star levels to render bar rows from JSX/template syntax instead of innerHTML. The math is entirely framework-agnostic.