Skip to content

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.

More micro-interactions components

← Browse all NudaUI components