Rating
Ratings allow users to view or provide feedback using a visual scale, typically stars.
Basic Rating
A simple star rating display.
<div class="Rating">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
</div>
<div class="Rating">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
</div>
Interactive Rating
Allow users to select a rating.
<div class="Rating Rating--interactive" role="radiogroup" aria-label="Rating">
<button class="Rating-star" role="radio" aria-checked="false" aria-label="1 star">
<i class="ph ph-star"></i>
</button>
<button class="Rating-star" role="radio" aria-checked="false" aria-label="2 stars">
<i class="ph ph-star"></i>
</button>
<button class="Rating-star" role="radio" aria-checked="false" aria-label="3 stars">
<i class="ph ph-star"></i>
</button>
<button class="Rating-star" role="radio" aria-checked="false" aria-label="4 stars">
<i class="ph ph-star"></i>
</button>
<button class="Rating-star" role="radio" aria-checked="false" aria-label="5 stars">
<i class="ph ph-star"></i>
</button>
</div>
<div class="Rating Rating--interactive" role="radiogroup" aria-label="Rating">
<button class="Rating-star" role="radio" aria-checked="false">
<i class="ph ph-star"></i>
</button>
<!-- Repeat for each star -->
</div>
Sizes
Ratings come in different sizes.
Small
Default
Large
<div style="display: flex; flex-direction: column; gap: var(--space-4);">
<div>
<span class="text-sm text-secondary">Small</span>
<div class="Rating Rating--sm">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
<i class="ph ph-star Rating-star"></i>
</div>
</div>
<div>
<span class="text-sm text-secondary">Default</span>
<div class="Rating">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
<i class="ph ph-star Rating-star"></i>
</div>
</div>
<div>
<span class="text-sm text-secondary">Large</span>
<div class="Rating Rating--lg">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
<i class="ph ph-star Rating-star"></i>
</div>
</div>
</div>
<div class="Rating Rating--sm">...</div>
<div class="Rating">...</div>
<div class="Rating Rating--lg">...</div>
With Count
Show the number of ratings alongside the stars.
<div style="display: flex; flex-direction: column; gap: var(--space-3);">
<div class="Rating-display">
<div class="Rating">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--half"></i>
</div>
<span class="Rating-value">4.5</span>
<span class="Rating-count">(128 reviews)</span>
</div>
<div class="Rating-display">
<div class="Rating Rating--sm">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
</div>
<span class="Rating-value Rating-value--sm">4.0</span>
</div>
</div>
<div class="Rating-display">
<div class="Rating">
<!-- Stars -->
</div>
<span class="Rating-value">4.5</span>
<span class="Rating-count">(128 reviews)</span>
</div>
Half Stars
Support for half-star precision.
<div style="display: flex; flex-direction: column; gap: var(--space-3);">
<div class="Rating">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star-half Rating-star Rating-star--half"></i>
<i class="ph ph-star Rating-star"></i>
<i class="ph ph-star Rating-star"></i>
<i class="ph ph-star Rating-star"></i>
</div>
<div class="Rating">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star-half Rating-star Rating-star--half"></i>
<i class="ph ph-star Rating-star"></i>
<i class="ph ph-star Rating-star"></i>
</div>
<div class="Rating">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star-half Rating-star Rating-star--half"></i>
<i class="ph ph-star Rating-star"></i>
</div>
</div>
<i class="ph-fill ph-star-half Rating-star Rating-star--half"></i>
Different Icons
Use hearts, thumbs, or custom icons.
Hearts
Thumbs
Emoji
<div style="display: flex; flex-direction: column; gap: var(--space-4);">
<div>
<span class="text-sm text-secondary">Hearts</span>
<div class="Rating Rating--hearts">
<i class="ph-fill ph-heart Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-heart Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-heart Rating-star Rating-star--filled"></i>
<i class="ph ph-heart Rating-star"></i>
<i class="ph ph-heart Rating-star"></i>
</div>
</div>
<div>
<span class="text-sm text-secondary">Thumbs</span>
<div class="Rating Rating--thumbs">
<button class="Rating-thumb Rating-thumb--up">
<i class="ph ph-thumbs-up"></i>
<span>42</span>
</button>
<button class="Rating-thumb Rating-thumb--down">
<i class="ph ph-thumbs-down"></i>
<span>3</span>
</button>
</div>
</div>
<div>
<span class="text-sm text-secondary">Emoji</span>
<div class="Rating Rating--emoji">
<button class="Rating-emoji">π</button>
<button class="Rating-emoji">π</button>
<button class="Rating-emoji Rating-emoji--selected">π</button>
<button class="Rating-emoji">π</button>
<button class="Rating-emoji">π€©</button>
</div>
</div>
</div>
<!-- Hearts -->
<div class="Rating Rating--hearts">
<i class="ph-fill ph-heart Rating-star Rating-star--filled"></i>
...
</div>
<!-- Thumbs -->
<div class="Rating Rating--thumbs">
<button class="Rating-thumb Rating-thumb--up">
<i class="ph ph-thumbs-up"></i>
<span>42</span>
</button>
<button class="Rating-thumb Rating-thumb--down">
<i class="ph ph-thumbs-down"></i>
<span>3</span>
</button>
</div>
<!-- Emoji -->
<div class="Rating Rating--emoji">
<button class="Rating-emoji">π</button>
<button class="Rating-emoji Rating-emoji--selected">π</button>
...
</div>
Rating Breakdown
Show distribution of ratings.
5 stars
65%
4 stars
20%
3 stars
10%
2 stars
3%
1 star
2%
<div class="Rating-breakdown">
<div class="Rating-breakdownRow">
<span class="Rating-breakdownLabel">5 stars</span>
<div class="Rating-breakdownBar">
<div class="Rating-breakdownFill" style="width: 65%;"></div>
</div>
<span class="Rating-breakdownCount">65%</span>
</div>
<div class="Rating-breakdownRow">
<span class="Rating-breakdownLabel">4 stars</span>
<div class="Rating-breakdownBar">
<div class="Rating-breakdownFill" style="width: 20%;"></div>
</div>
<span class="Rating-breakdownCount">20%</span>
</div>
<div class="Rating-breakdownRow">
<span class="Rating-breakdownLabel">3 stars</span>
<div class="Rating-breakdownBar">
<div class="Rating-breakdownFill" style="width: 10%;"></div>
</div>
<span class="Rating-breakdownCount">10%</span>
</div>
<div class="Rating-breakdownRow">
<span class="Rating-breakdownLabel">2 stars</span>
<div class="Rating-breakdownBar">
<div class="Rating-breakdownFill" style="width: 3%;"></div>
</div>
<span class="Rating-breakdownCount">3%</span>
</div>
<div class="Rating-breakdownRow">
<span class="Rating-breakdownLabel">1 star</span>
<div class="Rating-breakdownBar">
<div class="Rating-breakdownFill" style="width: 2%;"></div>
</div>
<span class="Rating-breakdownCount">2%</span>
</div>
</div>
<div class="Rating-breakdown">
<div class="Rating-breakdownRow">
<span class="Rating-breakdownLabel">5 stars</span>
<div class="Rating-breakdownBar">
<div class="Rating-breakdownFill" style="width: 65%;"></div>
</div>
<span class="Rating-breakdownCount">65%</span>
</div>
<!-- Repeat for each rating level -->
</div>
Readonly
Display-only rating (no interaction).
<div class="Rating Rating--readonly">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
</div>
<div class="Rating Rating--readonly">
<!-- Stars -->
</div>
Disabled
Dimmed, non-interactive state.
<div class="Rating Rating--disabled">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
<i class="ph ph-star Rating-star"></i>
</div>
<div class="Rating Rating--disabled">
<!-- Stars -->
</div>
With Label
Include a text label.
<div style="display: flex; flex-direction: column; gap: var(--space-4);">
<div>
<label class="Rating-label">How would you rate this product?</label>
<div class="Rating Rating--interactive" role="radiogroup">
<button class="Rating-star" role="radio"><i class="ph ph-star"></i></button>
<button class="Rating-star" role="radio"><i class="ph ph-star"></i></button>
<button class="Rating-star" role="radio"><i class="ph ph-star"></i></button>
<button class="Rating-star" role="radio"><i class="ph ph-star"></i></button>
<button class="Rating-star" role="radio"><i class="ph ph-star"></i></button>
</div>
</div>
<div>
<label class="Rating-label">
Your rating
<span class="Rating-required">*</span>
</label>
<div class="Rating Rating--interactive" role="radiogroup">
<button class="Rating-star Rating-star--filled" role="radio"><i class="ph-fill ph-star"></i></button>
<button class="Rating-star Rating-star--filled" role="radio"><i class="ph-fill ph-star"></i></button>
<button class="Rating-star Rating-star--filled" role="radio"><i class="ph-fill ph-star"></i></button>
<button class="Rating-star Rating-star--filled" role="radio"><i class="ph-fill ph-star"></i></button>
<button class="Rating-star" role="radio"><i class="ph ph-star"></i></button>
</div>
<span class="Rating-helper">4 out of 5 stars</span>
</div>
</div>
<label class="Rating-label">
Your rating
<span class="Rating-required">*</span>
</label>
<div class="Rating Rating--interactive" role="radiogroup">
<!-- Stars -->
</div>
<span class="Rating-helper">4 out of 5 stars</span>
JavaScript
// Interactive rating
document.querySelectorAll('.Rating--interactive').forEach(rating => {
const stars = rating.querySelectorAll('.Rating-star');
let currentRating = 0;
stars.forEach((star, index) => {
star.addEventListener('click', () => {
currentRating = index + 1;
updateStars();
});
star.addEventListener('mouseenter', () => {
highlightStars(index + 1);
});
});
rating.addEventListener('mouseleave', () => {
highlightStars(currentRating);
});
function updateStars() {
stars.forEach((star, i) => {
const icon = star.querySelector('i');
star.setAttribute('aria-checked', i < currentRating);
star.classList.toggle('Rating-star--filled', i < currentRating);
icon.className = i < currentRating ? 'ph-fill ph-star' : 'ph ph-star';
});
}
function highlightStars(count) {
stars.forEach((star, i) => {
const icon = star.querySelector('i');
icon.className = i < count ? 'ph-fill ph-star' : 'ph ph-star';
});
}
});
Common Patterns
Product Review Card
Customer Reviews
Based on 1,247 reviews
<div style="max-width: 400px; padding: var(--space-4); border: 1px solid var(--bd); border-radius: var(--r-m);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-3);">
<div style="font-weight: 600; font-size: 1.1rem;">Customer Reviews</div>
<div class="Rating-display">
<div class="Rating Rating--sm">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
</div>
<span class="Rating-value Rating-value--sm">4.2</span>
</div>
</div>
<div style="font-size: 0.85rem; color: var(--fg-3);">Based on 1,247 reviews</div>
</div>
Feedback Form
How was your experience?
<div style="max-width: 400px; padding: var(--space-4); background: var(--bg-s); border-radius: var(--r-m);">
<div style="font-weight: 600; margin-bottom: var(--space-3);">How was your experience?</div>
<div class="Rating Rating--interactive" role="radiogroup" aria-label="Experience rating" style="margin-bottom: var(--space-3);">
<button class="Rating-star Rating-star--filled" role="radio" aria-checked="true"><i class="ph-fill ph-star"></i></button>
<button class="Rating-star Rating-star--filled" role="radio" aria-checked="true"><i class="ph-fill ph-star"></i></button>
<button class="Rating-star Rating-star--filled" role="radio" aria-checked="true"><i class="ph-fill ph-star"></i></button>
<button class="Rating-star Rating-star--filled" role="radio" aria-checked="true"><i class="ph-fill ph-star"></i></button>
<button class="Rating-star" role="radio" aria-checked="false"><i class="ph ph-star"></i></button>
</div>
<span class="Rating-helper">4 out of 5 stars</span>
</div>
Compact List Item Rating
Wireless Headphones
USB-C Hub
<div style="display: flex; flex-direction: column; gap: var(--space-3); max-width: 350px;">
<div style="display: flex; justify-content: space-between; align-items: center; padding: var(--space-2) 0; border-bottom: 1px solid var(--bd);">
<span style="font-weight: 500;">Wireless Headphones</span>
<div class="Rating Rating--sm">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star-half Rating-star Rating-star--half"></i>
</div>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; padding: var(--space-2) 0; border-bottom: 1px solid var(--bd);">
<span style="font-weight: 500;">USB-C Hub</span>
<div class="Rating Rating--sm">
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph-fill ph-star Rating-star Rating-star--filled"></i>
<i class="ph ph-star Rating-star"></i>
<i class="ph ph-star Rating-star"></i>
</div>
</div>
</div>
Quick Satisfaction Survey
How helpful was this article?
<div style="text-align: center; padding: var(--space-4); background: var(--bg-s); border-radius: var(--r-m); max-width: 320px;">
<div style="font-weight: 500; margin-bottom: var(--space-3);">How helpful was this article?</div>
<div class="Rating Rating--emoji">
<button class="Rating-emoji">π</button>
<button class="Rating-emoji">π</button>
<button class="Rating-emoji Rating-emoji--selected">π</button>
<button class="Rating-emoji">π</button>
<button class="Rating-emoji">π€©</button>
</div>
</div>
Customization
Override rating styling with CSS custom properties:
/* Custom star colors */
.Rating {
--rating-color-empty: oklch(80% 0.02 0);
--rating-color-filled: oklch(65% 0.2 45);
}
.Rating-star { color: var(--rating-color-empty); }
.Rating-star--filled { color: var(--rating-color-filled); }
Custom Icon Size
.Rating--xl .Rating-star {
font-size: 2.5rem;
}
Brand Colors
/* Use brand blue instead of gold */
.Rating--brand .Rating-star--filled {
color: oklch(55% 0.2 260);
}
.Rating--brand .Rating--hearts .Rating-star--filled {
color: oklch(55% 0.25 350);
}
Theming
[data-theme="dark"] .Rating-star {
color: oklch(40% 0.02 0);
}
[data-theme="dark"] .Rating-star--filled {
color: oklch(80% 0.15 80);
}
API Reference
| Class | Description |
|---|---|
.Rating | Base rating container |
.Rating--sm | Small size variant |
.Rating--lg | Large size variant |
.Rating--interactive | Enables click/hover interactions |
.Rating--readonly | Display-only (no pointer events) |
.Rating--disabled | Dimmed, non-interactive state |
.Rating--hearts | Heart icon variant (red) |
.Rating--thumbs | Thumbs up/down variant |
.Rating--emoji | Emoji-based rating variant |
.Rating-star | Individual star element |
.Rating-star--filled | Filled/active star |
.Rating-star--half | Half-filled star |
.Rating-display | Container for rating + value + count |
.Rating-value | Numeric rating value |
.Rating-value--sm | Small value text |
.Rating-count | Review count text |
.Rating-thumb | Thumbs button container |
.Rating-thumb--up | Thumbs up button |
.Rating-thumb--down | Thumbs down button |
.Rating-emoji | Emoji button |
.Rating-emoji--selected | Selected emoji |
.Rating-breakdown | Rating distribution container |
.Rating-breakdownRow | Single breakdown row |
.Rating-breakdownBar | Progress bar track |
.Rating-breakdownFill | Progress bar fill |
.Rating-label | Label for rating input |
.Rating-required | Required field indicator |
.Rating-helper | Helper text below rating |
CSS Reference
/* Base rating container */
.Rating {
display: inline-flex;
align-items: center;
gap: var(--space-1);
}
/* Star element */
.Rating-star {
color: var(--bd-s);
font-size: 1.25rem;
transition: color 0.15s, transform 0.15s;
}
.Rating-star--filled,
.Rating-star--half {
color: oklch(75% 0.15 80);
}
/* Sizes */
.Rating--sm .Rating-star { font-size: 1rem; }
.Rating--lg .Rating-star { font-size: 1.75rem; }
/* Interactive */
.Rating--interactive .Rating-star {
cursor: pointer;
background: none;
border: none;
padding: var(--space-1);
}
.Rating--interactive .Rating-star:hover {
transform: scale(1.1);
}
.Rating--interactive .Rating-star:hover,
.Rating--interactive .Rating-star:hover ~ .Rating-star {
color: oklch(75% 0.15 80);
}
/* Display with value */
.Rating-display {
display: flex;
align-items: center;
gap: var(--space-2);
}
.Rating-value {
font-weight: 600;
font-size: var(--text-lg);
}
.Rating-value--sm { font-size: var(--text-sm); }
.Rating-count {
color: var(--fg-3);
font-size: var(--text-sm);
}
/* Hearts variant */
.Rating--hearts .Rating-star--filled {
color: oklch(60% 0.25 15);
}
/* Thumbs variant */
.Rating--thumbs {
gap: var(--space-3);
}
.Rating-thumb {
display: flex;
align-items: center;
gap: var(--space-1);
padding: var(--space-1) var(--space-2);
border: 1px solid var(--bd);
border-radius: var(--radius-sm);
background: transparent;
cursor: pointer;
transition: all 0.15s;
}
.Rating-thumb:hover {
background: var(--bg-s);
}
.Rating-thumb--up:hover { color: oklch(55% 0.15 150); }
.Rating-thumb--down:hover { color: oklch(55% 0.2 25); }
/* Emoji variant */
.Rating--emoji {
gap: var(--space-2);
}
.Rating-emoji {
font-size: 1.5rem;
background: none;
border: none;
cursor: pointer;
opacity: 0.5;
transition: all 0.15s;
padding: var(--space-1);
}
.Rating-emoji:hover,
.Rating-emoji--selected {
opacity: 1;
transform: scale(1.2);
}
/* Breakdown */
.Rating-breakdown {
display: flex;
flex-direction: column;
gap: var(--space-2);
max-width: 300px;
}
.Rating-breakdownRow {
display: flex;
align-items: center;
gap: var(--space-2);
}
.Rating-breakdownLabel {
font-size: var(--text-sm);
color: var(--fg-3);
min-width: 60px;
}
.Rating-breakdownBar {
flex: 1;
height: 8px;
background: var(--bg-s);
border-radius: var(--radius-full);
overflow: hidden;
}
.Rating-breakdownFill {
height: 100%;
background: oklch(75% 0.15 80);
border-radius: var(--radius-full);
}
.Rating-breakdownCount {
font-size: var(--text-sm);
color: var(--fg-3);
min-width: 40px;
text-align: right;
}
/* States */
.Rating--readonly { pointer-events: none; }
.Rating--disabled {
pointer-events: none;
opacity: 0.5;
}
/* Labels */
.Rating-label {
display: block;
font-size: var(--text-sm);
font-weight: 500;
margin-bottom: var(--space-1);
}
.Rating-required { color: oklch(55% 0.2 25); }
.Rating-helper {
display: block;
font-size: var(--text-xs);
color: var(--fg-3);
margin-top: var(--space-1);
}
Accessibility
Keyboard Support
| Key | Action |
|---|---|
Arrow Left / Arrow Right |
Navigate between stars |
Enter / Space |
Select the focused star |
Tab |
Move focus to/from the rating group |
Screen Reader Guidance
Use role="radiogroup" on the interactive container and role="radio" with aria-checked on each star button. Provide aria-label with the star count on each button (e.g., β3 starsβ).
<div class="Rating Rating--interactive" role="radiogroup" aria-label="Product rating">
<button class="Rating-star" role="radio" aria-checked="false" aria-label="1 star">
<i class="ph ph-star"></i>
</button>
<!-- ... -->
</div>
ARIA Attributes
role="radiogroup"on the rating containerrole="radio"andaria-checkedon each star buttonaria-labelwith star count on each buttonaria-labelon the container to describe the rating purpose- For read-only displays, use
aria-labelto convey the value (e.g., βRated 4 out of 5 starsβ) - Ensure visible focus indicators on interactive elements
- Provide sufficient color contrast for filled vs empty states
Best Practices
Do
- β Use labels with interactive ratings β Tell users what theyβre rating
- β Show the numeric value β β4.5 out of 5β alongside stars adds clarity
- β Support keyboard navigation β Arrow keys should move between stars
- β Provide helper text β Confirm the selection (βYou rated 4 starsβ)
- β Use half-stars for display β More precise representation of averages
- β Show review count β β(128 reviews)β adds social proof and credibility
Donβt
- β Use ratings without context β Stars alone donβt communicate whatβs being rated
- β Allow accidental submissions β Require confirmation for important ratings
- β Mix rating scales β Donβt use 5-star and 10-point in the same interface
- β Hide empty stars β Always show the full scale for reference
- β Use color alone to convey state β Filled vs empty needs shape or icon change too
- β Make stars too small on touch devices β Minimum 44px tap targets for mobile