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 loseWeight Exercise 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.

  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.

  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.

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

  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!

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

1 Ted J.

Thanks a lot for the help Paul

One last question, is there a way to hide the green stars when hovering, which makes the orange ones visible? The reason why is because I’d like to use a PNG image because they allow transparency/opacity,but I discovered that the orange stars are being loaded on top of the green ones, so when using a PNG image they’re still visible behind the orange ones, which looks bad.

2 Paul OB

Hi Ted,

You could hide the initial stars for IE7 upwards by doing this:

ul.rating:hover{background:none!important}

It would need a change of design for ie6 though.

3 Ted J.

Where would I put that in the CSS? Does it matter? I can’t seem to get it to work.

4 Paul OB

You can put anywhere you like as long as the ul that holds the stars is called .rating.

It will hide the green stars as soon as the stars are rolled over.

It won’t work in IE6 though.

5 Ted J.

Thanks a lot, it works perfectly now :)

6 azhar2day

this is wonderful ..

i read it 3 times and get a fantastic results and sure i put a copy of this lesson on my site here

http://www.azhar2day.com/vb

7 Sylwester w Górach

is there any whay to put it in the world press ?? it would be fine add to this script.

8 Paul OB

@Sylwester:Feel free to use the code in the article (at your own risk of course).

9 Chris P

Great Script! using it thx.

10 mobile crusher

I am new to this but Paul you will help me to undertand, I have done the first part the Grid or the matrix how you call it, (cool name) I have wanted to personalize it and instead of stars i did orange squares that makes a 6.32 high rows. Now I have discovered and I have already put to work your rating system it is really cool. Now I am trying to figure out how to put my own personalized picture instead of the stars. I want the rating system to be smaller which means I will have to change most of the numbers and that’s what I am trying to figure out. you said that I need to know the exact width and height of my rows Which it is giving me quite a little bit of work.

11 Paul OB

HI,

It shouldn’t be that hard to change the size of the images as long as you follow it through.

The stars were 16px by 16px in my example and all the positions were multiples of that:

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)

If your image was smaller then just reduce the above to match and then change the list and anchor sizes to match also.

I’d need to see an example to help any further :)

[…] CSS The Star Matrix Pre-loaded 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. […]

mulberry sale spyder womens jacket cheap new balance 574 mulberry outlet cheap new balance 574 arcteryx outlet mulberry sale spyder womens jacket mulberry sale spyder womens jacket mulberry outlet mulberry outlet new balance 574

Popular Articles

Top 10 Commentators


Subscribe to this feed! Subscribe by Email!

Random Bits Podcast

Blogs Worth Reading