May 23rd, 2007 - by Paul OB

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.

star-explanation1.png

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:

star-matrix1.gif

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.

HTML:
  1. <ul class="rating onestar">
  2. <li class="one"><a href="#" title="1 Star">1</a></li>
  3. <li class="two"><a href="#" title="2 Stars">2</a></li>
  4. <li class="three"><a href="#" title="3 Stars">3</a></li>
  5. <li class="four"><a href="#" title="4 Stars">4</a></li>
  6. <li class="five"><a href="#" title="5 Stars">5</a></li>
  7. </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.

CSS:
  1. .rating{
  2. width:80px;
  3. height:16px;
  4. margin:0 0 20px 0;
  5. padding:0;
  6. list-style:none;
  7. clear:both;
  8. position:relative;
  9. background: url(images/star-matrix.gif) no-repeat 0 0;
  10. }
  11. ul.rating li {
  12. cursor: pointer;
  13. /*ie5 mac doesn't like it if the list is floated but ie6 does\*/
  14. float:left;
  15. /* end hide*/
  16. text-indent:-999em;/* hide text*/
  17. }
  18. ul.rating li a {
  19. position:absolute;
  20. left:0;
  21. top:0;
  22. width:16px;
  23. height:16px;
  24. text-decoration:none;
  25. z-index: 200;
  26. }
  27. ul.rating li.one a {left:0}
  28. ul.rating li.two a {left:16px;}
  29. ul.rating li.three a {left:32px;}
  30. ul.rating li.four a {left:48px;}
  31. 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.

CSS:
  1. .nostar {background-position:0 0}
  2. .onestar {background-position:0 -16px}
  3. .twostar {background-position:0 -32px}
  4. .threestar {background-position:0 -48px}
  5. .fourstar {background-position:0 -64px}
  6. .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.)

CSS:
  1. ul.rating li a:hover {
  2. z-index:2;
  3. width:80px;
  4. height:16px;
  5. overflow:hidden;
  6. left:0;
  7. background: url(images/star-matrix.gif) no-repeat 0 0
  8. }
  9. ul.rating li.one a:hover {background-position:0 -96px;}
  10. ul.rating li.two a:hover {background-position:0 -112px;}
  11. ul.rating li.three a:hover {background-position:0 -128px}
  12. ul.rating li.four a:hover {background-position:0 -144px}
  13. 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/

Be sure to check out part 2 of this article for the back-end solution!

63 Responses to “CSS The Star Matrix Pre-loaded”

1 Dan Schulz

Nice article as always, Paul. :)

2 ses5909

Paul… that is sexy! I will definitely be using this one.

3 Golgotha

Paul is the Good Will Hunting of CSS!

4 Paul OB

Thanks Guys and girls its an interesting technique and well worth documenting :)

6 Jelena

This is just too cool, Paul! Thank you so much for sharing!

7 Ryan Graf

Great work as always Paul. Thanks for the contribution.

8 Brendon Kozlowski

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.

9 joe

doesn’t retain state-bah!

10 fastdump

I’m with Joe… The ‘take a look’ example doesn’t save the state of the selected rating. Have we missed something?…

11 Golgotha

@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.

12 Paul OB

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.

13 Alfred Fox

Very good explanation. Thanks for posting this.

14 Dean

What a cool trick! Now I need to come up with an application to use it on. Thanks Paul.

15 Newbie

Great tutorial! Anyone know of a guide to get the backend of the system running in PHP now?

16 Paul OB

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.

17 Dean
18 cpradio

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?

19 Paul OB

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:)

20 Golgotha

@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.

21 Foxarts

Absolute cool! Thanks

22 Peter Mansen

Not very complicate and nice effect!

23 Golgotha

@Foxtarts: Welcome to Search-This!

@Peter Mansen: Yeah, my boy Paul is wicked smart… Welcome to Search-This :)

24 k3k

this is realy an intresting article.
Thank you

25 CSS The Star Matrix Pre-loaded: Part 2

[...] reading Paul’s article “CSS The Star Matrix Pre-loaded”, I wanted to contribute by writing a back-end solution to the CSS [...]

26 felttippin

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

27 Jesse

Thanks Paul you are the CSS Master. This is a method I’ve never seen before, its AMAZING!!!

28 Coder

This is the coolest.

Thank you.

29 Best of May/June 2007

[...] 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. [...]

[...] CSS The Star Matrix Pre-loaded [...]

31 richard

realy nice post.. thnx

32 Mack

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?

33 No0oB

An extremely useful tutorial, thank you so much for sharing. I hope that I am allowed to use that star matrix on own websites?

34 Paul OB

@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 :)

35 CSS Star Matrix Preloaded - Article

[...] Go ahead and read the article [...]

36 Brent

Love the star rating system!! Any chance you could output a copy of the matrix image on a black background?

Thanks,
Brent

37 Paul OB

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

38 Best of May/June 2007 at Design Resources

[...] 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. [...]

39 Magic

Hello! How can i use the rating system in beta blogger?

40 Paul OB

@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/

41 CSS Resources | DefaultCss.com-CSS Portal

[...] CSS Star Rating System [...]

42 trademark registration

I like to know how to use the ratings system in beta blogger as well. Anyone?

43 Paul OB

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.

[...] 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. [...]

45 extreme webmaster

Amazing! I never realized this could be so easy. A-ma-zing. Congrats! I’ll be using this technique from now on.

46 Navigate-This

[...] 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 [...]

47 home

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

48 fitness

Mine refuses to show up in IE6 or IE7. I did change the star image size and it works ok in firefox.

49 Paul OB

Hi fitness, do you have a link to the problem page and I’ll take a look :)

50 nezh

Mine refuses to show up in IE6 or IE7. I did change the star image size and it works ok in firefox.

51 Paul OB

???? See post #49

52 kevin

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

53 Paul OB

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 :)

54 Kinks

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.

55 SEO Steve

These are some great examples. They are very helpful and useful. Thank you.

56 Fuzz

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;}

[...] which will change colour as you hover over them indicating the level at which to rate something.read more | digg [...]

58 amino

Really great work!
Could you clarify under which license are published all code snippets?

59 Sam

very nice code, thanks.

60 Lee

This method doesn’t require all those separate images… http://www.komodomedia.com/blog/2005/08/creating-a-star-rater-using-css/

61 Paul OB

@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.

62 thodo

thank you very much

63 PerS

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/

Share your thoughts...

WordPress Plugins

Blog Categories

Meta

Add this blog to my Technorati Favorites!

Popular Articles

Top 10 Commentators


Subscribe to this feed! Subscribe by Email!

Random Bits Podcast

You need to download the Flash player from Adobe

Blogs Worth Reading