Star ratings are very common on websites and usually are done with javascript. I can show you a way to do this only with css. So this is our basic scene:

We have 5 stars, each of them is a label tag that on click checks a radio button and that can be processed on page unload. The star rating is made with an image sprite that consists of 2 stars – the normal state and the hover state star.

The html code for this is the following:


I used labels that when clicked will check the linked radio buttons(only 1 at a time, because I used the same name attribute on them). The radio buttons are hidden so what the user can see are only the labels that have the star as a background.

    #rating { 
       background:url(../img/rating.png) repeat-x 0 0;
    #rating label { 
   #rating input[type=radio] {
     display: none

We have declared a background on the wrapper which is the #rating, also we put a width on it, otherwise it would repeat the background till the right edge of the screen and set an overflow hidden to avoid collapsing because of the floats inside. The label got the 13px dimensions(the width and height of the star) and float left to stay in 1 line.

   #rating:hover label {
      background:url(../img/rating.png)  0 -37px;
   #rating label:hover ~ label {
      background-position: 0 0;

This is the fun part. We catch the hover event on the wrapper and set on all of it’s children(label) the filled star background, but then since we are hovering with mouse on the wrapper we are also on one of it’s label tag in the same time (2 hovers in the same time – parent children). Every star that comes after that hovered label will have it’s background reset to the unfilled star.

Note: In order to have the amount of selected stars memorized, we have to change a little bit the structure but then also the css changes. So first, the html will look like this:


We reversed the whole list of labels, now the last is the first in the structure. We did this to have access to the previous elements, since css can access the next siblings not the previous siblings.Also the input comes first and then the label. Why? Because we will use float:right on everything (label and input) so even the structure shows that 5th star is the first and 1st star is the last, visually we will have the normal 1 – 2 – 3 – 4 – 5 star order because each element goes to the right of everything that is after it, so the first will be the last. We don’t need to catch the hover event on the parent. Since the float:right usage the ~ operator in our case will mean each previous sibling, at least visually previous, not structurally.

   #rating label,#rating input {

   #rating label:hover, #rating label:hover ~ label {
      background-position:0 -39px

   #rating input:checked ~ label {
      background-position:0 -39px

The input did not need a float:right because it is hidden anyway, but if you would show it, it would make sense in its order. There you have it, a hoverable and clickable star rating, all done only with css.

If you liked this article please rate, comment and subscribe.