Star Rating
A copy-paste micro-interactions component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.
Micro-interactionsHTMLCSSJavaScriptany framework
Copy into your project
HTML
<div class="nuda-star-rating" role="radiogroup" aria-label="Rating">
<button class="nuda-star-rating__star" data-value="1" aria-label="1 star">
<svg viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
</svg>
</button>
<button class="nuda-star-rating__star" data-value="2" aria-label="2 stars">
<svg viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
</svg>
</button>
<button class="nuda-star-rating__star" data-value="3" aria-label="3 stars">
<svg viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
</svg>
</button>
<button class="nuda-star-rating__star" data-value="4" aria-label="4 stars">
<svg viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
</svg>
</button>
<button class="nuda-star-rating__star" data-value="5" aria-label="5 stars">
<svg viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
</svg>
</button>
</div>CSS
/* Star Rating
Stars fill with golden color on hover/click.
Customize: --star-color */
.nuda-star-rating {
--star-color: #f59e0b;
display: inline-flex;
gap: 2px;
}
.nuda-star-rating__star {
background: none;
border: none;
cursor: pointer;
padding: 2px;
outline: none;
}
.nuda-star-rating__star svg {
width: 22px;
height: 22px;
fill: none;
stroke: #555;
transition: all 0.2s ease;
will-change: transform;
}
.nuda-star-rating__star:hover svg {
stroke: var(--star-color);
transform: scale(1.15);
}
.nuda-star-rating__star[data-filled="true"] svg {
fill: var(--star-color);
stroke: var(--star-color);
}
@media (prefers-reduced-motion: reduce) {
.nuda-star-rating__star svg { transition: none; }
}JavaScript
/* Star Rating — vanilla JS
Fills stars up to the clicked value. */
(function () {
document.querySelectorAll(".nuda-star-rating").forEach(function (group) {
var stars = group.querySelectorAll(".nuda-star-rating__star");
stars.forEach(function (star) {
star.addEventListener("click", function () {
var val = parseInt(star.getAttribute("data-value") || "0", 10);
group.setAttribute("data-rating", String(val));
stars.forEach(function (s, idx) {
s.setAttribute("data-filled", String(idx < val));
});
});
});
});
})();How to use Star Rating
Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.
Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.