call(back)
FrontendmediumSign in to star problems

Star Rating With Half Stars, at Scale

Build a star rating where a click fills every star up to the one clicked, then make it handle half stars, a thousand stars, and updates that are well optimised.

The default template is HTML/CSS/JS: write createStarRating(root, { max, value, onChange }) in star-rating.js, returning { value, set(next) }. The React template asks for a controlled <StarRating max value onChange /> instead.

Requirements

  • Clicking the left half of a star sets that star's half value (2.5 for the third star), and the right half sets the whole value. Half stars look half-filled.
  • The rating is one focusable control: role="slider" with aria-valuenow, aria-valuemin and aria-valuemax. The arrow keys step it by half a star, clamped at both ends.
  • With max at 1,000, the stars wrap inside their container, one listener serves all of them, and building them takes a single DOM insertion.
  • A change updates only the stars between the old and the new value. The HTML/CSS/JS demo counts the star elements each change writes to; the starter touches all 1,000.

Hints

Hint 1

Decide half or whole from where the click landed: compare event.clientX - box.left with half the star's getBoundingClientRect().width.

Hint 2

Build every star into a DocumentFragment and append it once. Put one click listener on the container, and find the star with event.target.closest(".star").

Hint 3

On a change from a to b, only stars with an index between floor(min(a, b)) and ceil(max(a, b)) can change their fill. Loop over just that range.

Asked at