Last Updated: February 25, 2016
·
19.18K
· amoniker

Star Ratings in CSS & UTF8

Ah, the ubiquitous star rating. A single simple concept with a hundred different implementations.

Let's make one using only UTF8 characters, CSS, and a single HTML element per star.

Here's what we'll be making: http://jsfiddle.net/M8UAy/

First, the markup:

<span class="star-icon">☆</span>
<span class="star-icon">☆</span>
<span class="star-icon">☆</span>
<span class="star-icon">☆</span>
<span class="star-icon">☆</span>

Keep it simple. This gives us five empty stars, but this protip is worth more than that!

Let's add some classes to fill in a solid 3.5 star rating. Satisfactory!

<span class="star-icon full">☆</span>
<span class="star-icon full">☆</span>
<span class="star-icon full">☆</span>
<span class="star-icon half">☆</span>
<span class="star-icon">☆</span>

Cool. Now we just need a little CSS. First, the grey, empty stars of dismay:

.star-icon {
    color: #ddd;
    font-size: 34px;
    position: relative;
}

Then - the bright, shining stars of triumph!

.star-icon.full:before {
    color: #FDE16D;
    content: '\2605'; /* Full star in UTF8 */
    position: absolute;
    left: 0;
    text-shadow: 0 0 2px rgba(0,0,0,0.7);
 }

And finally, the mediocre half-stars of indecision:

.star-icon.half:before {
    color: #FDE16D;
    content: '\2605'; /* Full star in UTF8 */
    position: absolute;
    left: 0;
    width: 50%;
    overflow: hidden;
    text-shadow: 0 0 2px rgba(0,0,0,0.7);
}

Check out that JSFiddle again if you want to see the result.

So, what's the trick here? We're using the empty star as a placeholder, then filling it in with the help of the CSS :before selector paired with the content property. This allows us to layer another full, yellow star on top.

The :before selector creates a pseudo-element whose content is the UTF8 . This pseudo-element is then positioned absolutely so that it covers the original empty star.

For the half-star, the trick is nearly the same, but we set width: 50%; and overflow: hidden; so that only half of the full-star shows up, while the rest is cut off.

You may have noticed a dirty Firefox hack in that JSFiddle. Unfortunately Firefox renders the stars at a much smaller size, so to compensate I've set the font-size higher for FF only. If you know what's causing this (or a better fix!) leave me a comment!

Also, it's possible to make the rating interactive on hover purely through CSS as well. Maybe something for my next protip ;)

★★★ 再见! ★★★

5 Responses
Add your response

This works on Safari, Chrome and Firefox, but not on IE11

over 1 year ago ·

@veganoo - strange... it works in IE8+ for me. Did you work out what's going on in IE11?

over 1 year ago ·

Not sure what's happening - not a coder ;-) have a look at veganoo.net at the post dated today (21st Nov)

over 1 year ago ·

@veganoo - I'd look into the meta tag which is being set on that page: <meta content='IE=EmulateIE7' http-equiv='X-UA-Compatible'/>. If that tag works in IE11 (which it appears to) then it would render without support for the :before pseudo-element necessary to fill in the stars.

over 1 year ago ·

Thanks amoniker, that's probably it.

over 1 year ago ·