Customer Review Card — Star Rating HTML CSS JS Snippet
Customer Review Card · Cards · Plain HTML, CSS & JS · Live preview
What's included
Features
voted class toggles on click — count increments/decrements optimistically. Green state confirms the vote without a toast or page reload.--av on each .avatar sets the background colour inline — one attribute per reviewer, supports any CSS colour value..star-empty span on trailing stars + a variant class (.stars-4, .stars-3) on the parent renders 4-star and 3-star ratings with grey unfilled stars..featured adds an indigo border and subtle gradient background — highlights the editor's pick or most helpful review..negative adds a red border — shows authenticity by surfacing lower-rated reviews alongside five-star ones.<span class="verified">✓ Verified</span> inside reviewer-meta renders a green checkmark badge inline with the review date..tags-row with .tag spans categorises review aspects (Quality, Value, Support). Easy to remove — just delete the tags-row div.repeat(2, 1fr) on desktop, single column on mobile via @media(max-width:600px). Cards adapt without layout shifts.About this UI Snippet
Customer Review Card — Star Rating System, Helpful Vote Toggle & Verified Badge Pattern

Customer review cards are a trust-building cornerstone of e-commerce, SaaS, and marketplace UIs. A well-designed review card communicates credibility — reviewer identity, star score, verification status, review content, and community validation (helpful votes) — in a compact, scannable format. This snippet builds a full review card grid with rating summary, avatar initials, star rating (full and partial), verified purchase badge, tag chips, togglable helpful vote button, and featured/negative card variants.
Review cards appear on product pages, SaaS pricing pages, testimonials sections, and marketplace listings. The design challenge is fitting reviewer identity, rating, content, and social proof signals into a card that works at both desktop (two-column grid) and mobile (single column) without feeling cramped.
Avatar initials with CSS custom property colour
Each avatar uses a two-letter initials abbreviation with a background colour set via --av CSS custom property. This approach avoids the complexity of loading user profile images while maintaining visual variety across reviewers. The gradient background uses background: var(--av) which accepts any CSS colour value — so you can pass hex, RGB, or gradient strings. The avatar is a fixed 36×36px rounded square (border-radius: 10px), matching the icon badge pattern from feature cards.
Star rating with partial fill
The full star rating uses HTML entity ★ (U+2605) styled with color: #f59e0b (amber). Partial ratings — 4-star and 3-star variants — use a .star-empty span for the unfilled portion styled in #e2e8f0 (light grey). This CSS-only approach requires no SVG masking or JavaScript calculations — just split the star characters at the rating boundary. For a more precise half-star or percentage fill, the svg-progress-ring technique applies.
Helpful vote toggle with optimistic UI
The "Helpful" button uses a voted class toggled by the vote(btn) function. On click, the count increments immediately (optimistic UI) and the button changes to green — no server round-trip required for the visual state. A second click reverses the vote. This pattern matches Amazon, Yelp, and Trustpilot's helpful vote interaction. The voted state uses background: #f0fdf4 with a green border — a clear confirmation state that doesn't require a modal or toast notification.
Featured and negative card variants
The .featured card uses a subtle indigo border (#c7d2fe) and light gradient background to elevate the highest-quality review. The .negative card uses a red border (#fecaca) — critical for authenticity; showing mixed reviews builds more trust than showing only five-star reviews. Both variants are pure CSS class additions requiring no structural HTML changes.
Rating summary bar
The section header shows the overall score as a large number (44px, weight 900) alongside star icons and review count. This "above-the-fold trust signal" pattern matches the approach used by Amazon's product pages and App Store listings. Pair this with a stats card for numeric KPI displays in dashboard contexts.
Build with AI
Build, Understand, Optimize, and Extend It With AI
You do not have to work out the partial-star technique by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how splitting literal star characters into a filled run followed by a separate star-empty span, combined with a stars-4 or stars-3 modifier class on the parent, produces a 4-star or 3-star display with no SVG or JavaScript math involved. The same assistant can help you optimize it — ask whether the vote function's approach of parsing textContent back into an integer on every click is fragile compared to tracking the count as actual JavaScript state per card. It's also useful for extending the card grid: ask it to add sorting controls (most helpful, most recent, highest rated), wire the report button to an actual moderation flow with a confirmation step, or add pagination or infinite scroll once the review count grows large. 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:
Build a customer review card grid in plain HTML, CSS, and JavaScript with no library.
Requirements:
- Render a rating summary header showing a large aggregate numeric score next to a row of star characters and a review count, all in plain text and CSS (no images, no SVG stars).
- Render each review as a card containing a colored initials avatar (the background color must be set via a CSS custom property assigned inline per card, not a hardcoded class per color), a reviewer name, a date, an optional verified badge, a star rating, a title, a body paragraph, and an optional row of category tag chips.
- Implement partial star ratings (e.g. exactly 4 out of 5, or 3 out of 5) using only literal star characters: render the filled stars as plain text in an accent color, then wrap the remaining unfilled stars in a separate span with a distinct modifier class that renders them in a muted gray color — no SVG masking, no percentage-based clipping.
- Add a "Helpful" vote button on every card that toggles between an unvoted and voted visual state on click, incrementing a visible numeric count when voted and decrementing it back when un-voted, with each button's state tracked completely independently of every other card's button.
- Support at least two special card variants purely through CSS class additions with no structural HTML differences: a "featured" variant with a distinct accent border and background tint, and a "negative" (lower-rated) variant with a distinct warning-colored border, since showing some critical reviews alongside positive ones is itself a trust signal.
- Lay the cards out in a responsive CSS grid: two columns on wider viewports collapsing to a single column below a set breakpoint.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
- 1Paste HTML, CSS, and JSA two-column review grid appears with a rating summary above. Four review cards show — featured (indigo border), standard, and negative (red border) variants.
- 2Click any Helpful buttonThe button turns green, the count increments by one. Click again to un-vote and decrement. Each button tracks its own vote state independently.
- 3Change the avatar colourEach
.avatarhas an inlinestyle="--av:#colour"attribute. Pass any CSS colour — hex, hsl, or even a gradient string — to customise each reviewer's avatar. - 4Set the star ratingUse full ★ characters for filled stars and wrap empty stars in
<span class="star-empty">★</span>. Add.stars-4or.stars-3to the parent for the right grey styling. - 5Add a featured reviewAdd
class="review-card featured"for the indigo-bordered highlight card. Addclass="review-card negative"for a red-bordered lower-rated review. - 6Swap review contentReplace reviewer name, date, title, body, and tag chips. Add or remove
<span class="tag">elements inside.tags-rowfor category labels.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
Add a .rating-bars section to the rating summary. Each bar is a <div class="bar-row"> containing the star label, a <div class="bar-fill" with a percentage width, and a count. Use CSS transition on width for an animated fill on page load.
Add a "Load more" button below the grid. On click, fetch more reviews via API, create card elements from a template, and append them to .reviews-grid. For infinite scroll, use an IntersectionObserver on a sentinel element below the last card. See the infinite scroll snippet.
Add a <select> sort control above the grid. On change, read the sort value, sort the review data array, and re-render the cards. Store review objects in a JS array with date, helpful, and rating fields for easy sorting.
Create a ReviewCard component accepting {name, date, rating, title, body, tags, helpfulCount, verified, variant} props. The helpful vote state becomes const [voted, setVoted] = useState(false) and const [count, setCount] = useState(helpfulCount). The parent ReviewGrid maps a reviews array to ReviewCard instances.