Recently I had to create a Star Rating system for a client so I thought I'd share with you the techniques I used to accomplish this. If you are not familiar with a Star Rating System, it's simply a method of voting using (usually) 5 stars in a row, which will change colour as you hover over them indicating the level at which to rate something.
You may think a simple rollover would accomplish this but difficulty arises because as you rollover each star it should stay highlighted while you light up the next one and so on until the end of the row of stars. If this doesn't make much sense to you then take a look at what we are going to achieve in this article. (I will leave the server-side coding to someone more knowledgeable and we will just concentrate on the visual aspects of making this effect happen. )
As you can see from the demo the stars stay hovered as you rollover each one. However, as mentioned earlier, the complicated part is that as each star is hovered it should stay alight while the next one is hovered so that if you start at the left side then 1,2,3,4 and 5 stars will be alight as you traverse the row. Usually a rollover will only be active on the anchor that the pointer is currently over making previous anchors lose their focus and thus their hover effect disappear. A number of current examples use JavaScript to help with this effect but we'll show that it can be done without any JavaScript at all.
An added difficulty was that the client also wanted any stars that were already lit up (i.e. they already had a default rating) to be switched off when any star was hovered. This means we not only have to keep all the hovered stars alight but we have to turn off the different coloured default rating state.
This is best shown with a screenshot with the mouse pointer at different positions within the row to show the effect I described.

As you can see there is a lot to accomplish here and from all the Star Rating systems I've seen so far, none of them accomplish all the above criteria without scripting. I should point out that there are a number of CSS Star Rating articles written already and although this article was produced in isolation the techniques used will be similar because there is really only one way that this can be accomplished. Therefore I cannot claim this method is entirely unique but it does have some extra features.
The Matrix Pre-loaded
The first thing we need to do is to create the images needed for the demonstration - this is not as simple as it seems. In fact the construction of the image is vital to the end result and must be constructed carefully. To avoid rollover delays we are going to use a single image that contains all the states of the rollover buttons. We also avoid any rollover delay by preloading the image when the page first loads. As the image contains many rows of stars we will simply use the background position to manipulate which set of images need to be seen for a particular state.
This is the image we will be using:

If you study the image you will see that it contains every combination of what could be expected from rolling over any of the stars. It also allows us to set the default rating state. To display any particular row we simply adjust the background-position property to bring into view the row we need. Of course we need to know the exact height of each row to ensure that the element displays correctly.
Into the code we go:
The HTML is actually the simplest part of this demo - we use a basic unordered list.
-
<ul class="rating onestar">
-
</ul>
To identify each list item correctly we apply a class. The UL itself has 2 classes added to it. The first class (rating) is the basic styling and the second class (onestar) is the default rating. (If you haven't come across multiple classes before then read this article which explains them in detail.) The onestar class could be changed to another classname to reflect the current default, so you need to set up 5 classes for this. I've used names such as onestar, twostar, threestar etc. Don't be tempted to use digits such as 1star, 2star etc as it is not valid and will be ignored by some browsers because id's and classes can't begin with a digit.
The UL has a fixed width and height so we apply the initial default state of the star rating to the background of the UL. In the code above we want one star alight so we add a class of onestar to the UL.
Next, we position our anchors over each star in the image using absolute positioning. It doesn't matter that the absolute element is removed from the flow because the UL itself is not position absolute and therefore will preserve the flow of the document. To place the anchors inside the UL we set the UL to have a position:relative and thus define a stacking context for further positioned elements.
I have floated the list elements because this keeps IE6 happy.
-
.rating{
-
width:80px;
-
height:16px;
-
margin:0 0 20px 0;
-
padding:0;
-
list-style:none;
-
clear:both;
-
position:relative;
-
background: url(images/star-matrix.gif) no-repeat 0 0;
-
}
-
ul.rating li {
-
cursor: pointer;
-
/*ie5 mac doesn't like it if the list is floated but ie6 does\*/
-
float:left;
-
/* end hide*/
-
text-indent:-999em;/* hide text*/
-
}
-
ul.rating li a {
-
position:absolute;
-
left:0;
-
top:0;
-
width:16px;
-
height:16px;
-
text-decoration:none;
-
z-index: 200;
-
}
-
ul.rating li.one a {left:0}
-
ul.rating li.two a {left:16px;}
-
ul.rating li.three a {left:32px;}
-
ul.rating li.four a {left:48px;}
-
ul.rating li.five a {left:64px;}
The anchors are empty elements apart from a number which has been hidden using text-indent, but you may want to use a more suitable image-replacement method as I didn't want to over complicate things here. With the code above we have placed the default state in the background and have now positioned a 16px by 16px anchor over the top of each star to match exactly. Each list needs a class (li.one, li.two etc) so that we can move the anchor into the correct position. Dimensions are critical so make sure you match them carefully.
To set the initial state we need to create our five main classes so that the background position can be changed.
-
.nostar {background-position:0 0}
-
.onestar {background-position:0 -16px}
-
.twostar {background-position:0 -32px}
-
.threestar {background-position:0 -48px}
-
.fourstar {background-position:0 -64px}
-
.fivestar {background-position:0 -80px}
We are using the same image but by changing the background position we can set whatever default we need to using the original matrix for reference.
So far we have not done anything clever (apart from the image construction) -- we still need to work out how to hover and hold the previous stars alight while at the same time clear the colour from the stars to the right.
Now you see it - Now you don't.
Hold on to your hats as here comes the clever stuff. Each anchor is only 16px wide and positioned at 16px intervals along the row but we are now going to change the width and position on hover so that a whole row of images can be overlaid over the existing row. This is done by changing the width of the anchor on hover only and then setting the left position back to the beginning of the row. The effect is that a whole row of 5 stars are overlaid over the default state and creates a new row with the default state apparently turned off and the hovered items lit up. All that needs to be done is to select the correct background image to show for each anchor in the row.
However, the problem isn't completely solved because when the mouse is now moved back to the left over another star the image displayed just stays the same because we have one anchor basically on top of all the others and at full width. We need some way to keep the effect we have but allow the anchors underneath to apply their hovered images in turn. Luckily we can do this by setting the original anchors to have a higher z-index than the hovered anchor. This will allow the background to stretch full width but keep the anchors on top so that a new image can be effected on rollover.
Therefore on hover we not only change the width and position we also reduce the z-index.
Here is the code to do all the above (Note that IE6 requires overflow:hidden here or it will show some of the image below.)
-
ul.rating li a:hover {
-
z-index:2;
-
width:80px;
-
height:16px;
-
overflow:hidden;
-
left:0;
-
background: url(images/star-matrix.gif) no-repeat 0 0
-
}
-
ul.rating li.one a:hover {background-position:0 -96px;}
-
ul.rating li.two a:hover {background-position:0 -112px;}
-
ul.rating li.three a:hover {background-position:0 -128px}
-
ul.rating li.four a:hover {background-position:0 -144px}
-
ul.rating li.five a:hover {background-position:0 -160px}
If you are wondering where the numbers come from for the background position then you should refer to the original matrix image and you can see that as each star is 16px high we can work out which image to show at which stage by using the correct height.
Here is a little text matrix that should make it clear what number to use:
key: B=Blank star: O=Orange Star: G = Green Star
colours ... .Background position
B B B B B - (0 0)
G B B B B - (0 -16px)
G G B B B - (0 -32px)
G G G B B - (0 -48px)
G G G G B - (0 -64px)
G G G G G - (0 -80px)
O B B B B - (0 -96px)
O O B B B - (0 -112px)
O O O B B - (0 -128px)
O O O O B - (0 -144px)
O O O O O - (0 -160px)
That's about all there is to it! The above code should work in most browsers -- I have tested in ie5 mac, Safari 1.2, ie5 - 7, Firefox 2 and Opera 9 and all seem to behave correctly. However, I would assume that some older browsers may not like the changes we make on hover so make sure as usual you test in the browsers you want to support.
Please refer to the demo for the full source code and CSS.
Further Reading:
http://wellstyled.com/css-nopreload-rollovers.html
http://sandbox.wilstuckey.com/jquery-ratings/
http://komodomedia.com/blog/index.php/2006/01/09/css-star-rating-part-deux/

May 23rd, 2007 at 7:47 am
Nice article as always, Paul.
May 23rd, 2007 at 7:57 am
Paul… that is sexy! I will definitely be using this one.
May 23rd, 2007 at 7:58 am
Paul is the Good Will Hunting of CSS!
May 23rd, 2007 at 8:10 am
Thanks Guys and girls its an interesting technique and well worth documenting
May 23rd, 2007 at 8:15 am
dugg here: http://digg.com/programming/CSS_Star_Matrix_Rating_System/
May 23rd, 2007 at 9:00 am
This is just too cool, Paul! Thank you so much for sharing!
May 23rd, 2007 at 7:29 pm
Great work as always Paul. Thanks for the contribution.
May 23rd, 2007 at 7:31 pm
Awesome, absolutely awesome. Thanks, Paul!
Hmmm…should the IE specific styles (such as overflow: hidden) be placed in separate conditional stylesheets? I’ve been using this method, but according to the somewhat dated “Webpage Speed Report”, it suggests not using more than a single stylesheet (or using @import). I much prefer to use standards over hacks, but at the same time, I still have visitors using a connection speed similar to 28.8 bps modems. I often have to balance some interesting things.
May 23rd, 2007 at 8:39 pm
doesn’t retain state-bah!
May 24th, 2007 at 2:29 am
I’m with Joe… The ‘take a look’ example doesn’t save the state of the selected rating. Have we missed something?…
May 24th, 2007 at 6:46 am
@joe and fastdump: the reason the state is not being saved is because there is no server-side code to save the state. The example only shares the client-side code. In order to save the state you would have to use PHP or .NET or otherwise to write what the person clicked on to a database or other storage device.
May 24th, 2007 at 7:23 am
Yes, as Mark said above and as I mentioned in the article this is just the front end and you would of course need to write the serverside code to reconcile your votes and re-display the updated details. Which can easily be done by swapping the class in the ul as appropriate.
May 24th, 2007 at 11:47 am
Very good explanation. Thanks for posting this.
May 24th, 2007 at 12:15 pm
What a cool trick! Now I need to come up with an application to use it on. Thanks Paul.
May 24th, 2007 at 4:31 pm
Great tutorial! Anyone know of a guide to get the backend of the system running in PHP now?
May 24th, 2007 at 6:36 pm
I’m afraid my expertise is strictly CSS and I usually leave the back-end to the programmers.
There are a few examples around and you may find more info from the links in the article. Or somewhere like this:
http://www.yvoschaap.com/index.php/weblog/css_star_rater_ajax_version/
However you would have to adapt it of course.
May 25th, 2007 at 10:16 am
Newbie read my mind; I was thinking the exact same thing and found these yesterday:
Masuga - Unobtrusive AJAX Star Rating Bar
Slim - Creating a star rating system part 2
Slim - Creating a star rating system part 3
Slim - Star rating , maintaining state
May 25th, 2007 at 1:11 pm
I’ll write an article on Search-This integrating Paul’s front-end with a backend. Any suggestions? Do you want it to be AJAX capable or physical posting the page to the backend?
May 25th, 2007 at 2:58 pm
Hey Matt, That would be a good idea if you could show how the back end works. I would suggest that you describe what you think is the most appropriate way to do it:)
May 25th, 2007 at 3:07 pm
@Matt: cool, I would go Ajax to PHP to MySQL. That way it can show n number of votes and when they click on a link it updates to n+1 automagically without needing a page reload to see that my vote was counted.
May 28th, 2007 at 6:14 am
Absolute cool! Thanks
May 28th, 2007 at 3:13 pm
Not very complicate and nice effect!
May 28th, 2007 at 3:31 pm
@Foxtarts: Welcome to Search-This!
@Peter Mansen: Yeah, my boy Paul is wicked smart… Welcome to Search-This
May 29th, 2007 at 1:36 am
this is realy an intresting article.
Thank you
June 4th, 2007 at 7:19 am
[...] reading Paul’s article “CSS The Star Matrix Pre-loaded”, I wanted to contribute by writing a back-end solution to the CSS [...]
June 5th, 2007 at 5:34 pm
I’ve put together an extensive article similar to your post on how to use the star rating system from komodomedia using Ruby on Rails.
You can read it here
June 16th, 2007 at 1:28 am
Thanks Paul you are the CSS Master. This is a method I’ve never seen before, its AMAZING!!!
June 28th, 2007 at 3:01 pm
This is the coolest.
Thank you.
July 9th, 2007 at 6:03 am
[...] CSS The Star Matrix Pre-loaded This tutorial describes the design and programming of a star rating system, a method of voting using (usually) 5 stars in a row, which will change colour as you hover over them indicating the level at which to rate something. [...]
July 10th, 2007 at 7:01 am
[...] CSS The Star Matrix Pre-loaded [...]
July 12th, 2007 at 5:59 am
realy nice post.. thnx
July 12th, 2007 at 9:32 pm
Mine refuses to show up in IE6 or IE7. I did change the star image size and it works ok in firefox. Could someone tell me w here I went wrong?
July 15th, 2007 at 4:44 am
An extremely useful tutorial, thank you so much for sharing. I hope that I am allowed to use that star matrix on own websites?
July 17th, 2007 at 6:04 am
@Mack, We would need to see what you have done to give an answer to this as it could be anything. Do you have a link to the problem.
@NoOoB - You can use the code wherever you like
July 18th, 2007 at 1:42 am
[...] Go ahead and read the article [...]
July 20th, 2007 at 10:13 am
Love the star rating system!! Any chance you could output a copy of the matrix image on a black background?
Thanks,
Brent
July 20th, 2007 at 12:39 pm
Hi Brent,
I changed the image background to black (transparent) but you will still need to edit some of the pixels on the stars themselves to make it look better.
http://www.pmob.co.uk/temp/star-ratingblack.htm
July 27th, 2007 at 6:15 am
[...] CSS The Star Matrix Pre-loaded This tutorial describes the design and programming of a star rating system, a method of voting using (usually) 5 stars in a row, which will change colour as you hover over them indicating the level at which to rate something. [...]
August 19th, 2007 at 6:13 am
Hello! How can i use the rating system in beta blogger?
August 19th, 2007 at 12:33 pm
@magic - See the follow up article for the back end implementation methods.
http://www.search-this.com/2007/06/04/css-the-star-matrix-pre-loaded-part-2/
November 3rd, 2007 at 3:39 am
[...] CSS Star Rating System [...]
November 8th, 2007 at 2:36 am
I like to know how to use the ratings system in beta blogger as well. Anyone?
November 8th, 2007 at 9:03 am
Sorry I don’t know anything about beta blogger but you might find some information in the server side half of this article:
http://www.search-this.com/2007/06/04/css-the-star-matrix-pre-loaded-part-2/
Or post your query in that thread.
December 5th, 2007 at 2:25 am
[...] CSS/XHTML only design and tutorial is called the CSS The Star Matrix Pre-loaded. This tutorial is clearly written and images are provided to use when you create the rating system. [...]
December 15th, 2007 at 4:03 pm
Amazing! I never realized this could be so easy. A-ma-zing. Congrats! I’ll be using this technique from now on.
December 19th, 2007 at 8:29 am
[...] this article we are going to re-visit a technique we first learned in the Star Matrix Pre-loaded article, except that this time we are going to use it to produce a navigation menu. Before we start it may [...]
January 19th, 2008 at 5:29 am
CSS/XHTML only design and tutorial is called the CSS The Star Matrix Pre-loaded. This tutorial is clearly written and images are provided to use when you create the rating system
February 1st, 2008 at 3:47 pm
Mine refuses to show up in IE6 or IE7. I did change the star image size and it works ok in firefox.
February 2nd, 2008 at 4:10 am
Hi fitness, do you have a link to the problem page and I’ll take a look
February 3rd, 2008 at 9:33 am
Mine refuses to show up in IE6 or IE7. I did change the star image size and it works ok in firefox.
February 3rd, 2008 at 2:47 pm
???? See post #49
February 22nd, 2008 at 11:30 pm
Hi. I have seen similar but this works really well. I have used it on my local community directory site. However, I added one bit so that the href=”#” doesn’t cause a jump to the top of the page. In the onclick, after any calls to a function you may have (you may have none) just put “return false;”. This does the trick! Example
Cheers
February 23rd, 2008 at 8:01 am
Hi Kevin,
Glad you found it useful and thanks for your comments
Did you see Matt’s back end solution for this:
http://www.search-this.com/2007/06/04/css-the-star-matrix-pre-loaded-part-2/
To stop the link jumping to the top of the page you could just add a non existent ID like this in the anchors href : href=”#nowhere”
However, if you are using javascript then the anchors should really lead you to a valid destination where users without javascript enabled can vote
April 27th, 2008 at 12:26 pm
A good tutorial, here’s an example that only uses 3 rows of stars and a left offset to achieve the same effect: http://mooka.ath.cx/stareg/
I suppose the only advantage is that creating the star image is less tedious, assuming you want each row to use the same color.
May 7th, 2008 at 8:54 am
These are some great examples. They are very helpful and useful. Thank you.
May 15th, 2008 at 3:02 am
to get rid of that annoying focus outline that firefox adds to the stars that have been selected just add the ‘-moz-outline:none;’
property to your anchor css
eg :
ul.rating li.one a {left:0;-moz-outline:none;}
ul.rating li.two a {left:16px;-moz-outline:none;}
ul.rating li.three a {left:32px;-moz-outline:none;}
ul.rating li.four a {left:48px;-moz-outline:none;}
ul.rating li.five a {left:64px;-moz-outline:none;}
June 13th, 2008 at 7:28 am
[...] which will change colour as you hover over them indicating the level at which to rate something.read more | digg [...]
August 8th, 2008 at 10:26 am
Really great work!
Could you clarify under which license are published all code snippets?
August 17th, 2008 at 1:33 pm
very nice code, thanks.
August 30th, 2008 at 4:25 pm
This method doesn’t require all those separate images… http://www.komodomedia.com/blog/2005/08/creating-a-star-rater-using-css/
September 11th, 2008 at 1:59 pm
@Lee: My method only uses 1 image so I don’t know what you mean.
Also my method is better as it turns off the other stars when you roll over the first star which that method you linked to doesn’t do and makes it hard to select less stars because all the stars stay on.
September 25th, 2008 at 7:34 am
thank you very much
October 6th, 2008 at 5:50 pm
very nice, thank you for sharing this.
I used it to write a ajax rating snippet for facebook. You can see it here: http://apps.new.facebook.com/ajaxrating/