Rating

별점

A control where filling in star-like icons expresses a score on a fixed scale, typically out of five.

Also known as: Star ratingScore picker
···
html
<div class="rt">
  <div class="stars" id="stars" role="radiogroup" aria-label="평점">
    <button role="radio" aria-checked="false" data-v="1">★</button>
    <button role="radio" aria-checked="false" data-v="2">★</button>
    <button role="radio" aria-checked="false" data-v="3">★</button>
    <button role="radio" aria-checked="false" data-v="4">★</button>
    <button role="radio" aria-checked="false" data-v="5">★</button>
  </div>
  <span class="rtval" id="rtval">0.0 / 5</span>
</div>
css
.rt{display:grid;place-items:center;gap:10px}
.stars{display:flex;gap:2px}
.stars button{border:0;background:none;font-size:26px;line-height:1;color:var(--line);cursor:pointer;padding:2px;transition:color .12s}
.stars button[data-fill]{color:#f5b32a}
.rtval{font-size:12px;color:var(--muted);font-weight:600}
js
const stars = [...document.querySelectorAll('.stars button')];
const val = document.getElementById('rtval');
function paint(n) {
  stars.forEach((s) => { s.toggleAttribute('data-fill', Number(s.dataset.v) <= n); s.setAttribute('aria-checked', String(Number(s.dataset.v) === n)); });
  val.textContent = n.toFixed(1) + ' / 5';
}
let auto = true, committed = 0;
stars.forEach((s) => {
  s.addEventListener('mouseenter', () => paint(Number(s.dataset.v)));
  s.addEventListener('click', () => { auto = false; committed = Number(s.dataset.v); paint(committed); });
});
document.querySelector('.stars').addEventListener('mouseleave', () => paint(committed));
function loop() {
  if (!auto) return;
  let n = 0;
  const fill = setInterval(() => {
    if (!auto) return clearInterval(fill);
    n++;
    paint(n);
    if (n >= 4) { clearInterval(fill); setTimeout(() => { if (auto) { paint(0); setTimeout(loop, 700); } }, 1200); }
  }, 220);
}
setTimeout(loop, 500);

Wrap it in role="radiogroup" and make each star role="radio" (or use five visually-hidden radio inputs) so it behaves exactly like a radio group where exactly one score is chosen. The star shape carries no meaning to a screen reader on its own, so the value needs to be read as text — "3 out of 5 stars."

The difference from a slider is continuous vs. discrete — a slider handles any value along a range, while a rating is a small, exact scale (1, 2, 3…) that can be counted at a glance by icon.

Distinguish the hover "preview" fill from the click "commit" — a score shouldn't be saved to the server just because the pointer passed over it.