An updated and more cross-browser compatible version of the CSS star rater can be found here.

My last CSS tutorial, Creating a Star Rater Using CSS covered the creation of a 5-star rating system using only CSS and a list of links. The result acheived can be seen below:

Rate me!
Here is the original CSS star rater in all of its goodness. However, I have mixed it up a little to show that this system is decently flexible. In this case, I have changed the background images for the star graphics and made them a little larger.

Now, this rater works great in practice, but it is missing one essential thing: state. This star rating system does not have a initial state exept for a zero star rating. This is not good enough. We need to be able to start off with a specific rating, say 4 stars or 3 stars. Better yet would be a rating of 3.5 stars. As you know, when you average a rating from many users, you will most likely not get an exact integer number. Most likely you will come up with a rating such as 3.76 stars. How do you do this with CSS? That is the question I aim to answer.

If you don’t understand how the CSS works for the basic star rater that you see above, be sure to do your homework and head on over to the original article for the CSS star rating before you continue.

Now, I hate over complicating things, so I am going to keep this as straight forward as possible. First I will introduce you to my solution to this issue, I will then explain my approach, then I will present you with the CSS and a brief explanation of how it works.

Step 1: Check it in action

Everybody wants to see the result before they do the work, so lets do that. Here she is, in her full shiny glory:

Here’s a few more:

2.5 stars

0 stars

4 stars

Step 2: The XHTML

<ul class='star-rating'>
<li class='current-rating'>Currently 3.5/5 Stars.</li>
<li><a href='#' title='1 star out of 5' class='one-star'>1</a></li>
<li><a href='#' title='2 stars out of 5' class='two-stars'>2</a></li>
<li><a href='#' title='3 stars out of 5' class='three-stars'>3</a></li>
<li><a href='#' title='4 stars out of 5' class='four-stars'>4</a></li>
<li><a href='#' title='5 stars out of 5' class='five-stars'>5</a></li>
</ul>

Basically, the star rater is setup exactly the same way as previously shown. The only difference you will see is in bold. All that we have done here is add one more list element. This element has a class of “current-rating” and has some descriptive text for those browsers that aren’t too cool with CSS. Also, this text is great for screen readers. Don’t worry about this text showing up because we are going to push it off the screen and show the graphical equivalent of 3.5 stars in its place. Pretty simple huh?

Step 3: The Star Image

Don’t ask me why, but we are going to create the star image just a little differently. We are going to make a 3-state image. State 1 will be for the empty, non-rated star. State 2 will be for the current rating. State 3 will be for the user’s rating. Basically the user will hover the star rater and see a different state for when they are choosing their rating. Nifty.

Why a different state image and not just reset the image when a user hovers, using the already showing state? Good question and I am very glad that you asked it. When I first created this thing, I had that same idea. Without boring you with the headache that I had, let me say that it involved me making the list element that housed the current rating a link, then when that link was hovered, I made the width of the link set to 0. Well, as you may have thought, the resulting outcome in IE and Firefox was really really jacked up. It would flicker like heck and do a crazy song and dance and was really unfriendly. Then, I thought to myself, self what should we do? The troubles came from the current state being a link and the links being unfriendly on top of eachother, so I decided to make it a list element with the hover event on the list element like so: li:hover. If any of you know what comes next is pretty dang frustrating to all CSS developers. You got it. Some evil nerd with a lot of money made a proprietary browser that does NOT support :hover pseudo events on list elements. Basically, to make this solution work in IE, you have to get all crazy up in your code and include a csshover.htc file to make the browser realize how to make hover events work. Only problem. You HAVE to have JavaScript turned on. Screw that.

It came to me in a dream. Have a 3-state star rater. This will fix the problem. Hence we find ourselves with this 3-state star image that is o-so-beautiful:

Star Rater Dimensions

Step 4: The CSS, the Magic

  1. .star-rating li.current-rating{
  2. background: url(star_rating.gif) left bottom;
  3. position: absolute;
  4. height: 30px;
  5. display: block;
  6. text-indent: -9000px;
  7. z-index: 1;
  8. }

This time around, we are building on the previous CSS from the tutorial creating a star rater using CSS so the CSS should be pretty small.

The first CSS code that you will notice is the background tag. This list element will have…you guessed it, the same background as all of the other elements. In this case the background has three states: unrated, rated, and currently rating. Keep in mind that some CSS has changed from the original article to make the new background image work for this three state rater. Back to the rater. This list element will contain the current rating for whatever object/article you are using it for.

The next line of CSS is the position:absolute. Because the containing UL of this rater is positioned relatively, that means that this list will be relatively absolute. So if this list element is put at coordinates left:0px, top:0px, it will be located at those coordinates relative to the parent unordered list, NOT to the main window.

The next CSS rules are pretty simple. height:30px does what you think it does – it forces the height of the li element to be as high as all of the other stars. The display:block rule is in place because in the previous tutorial the style .star-rating li declares the list element to be a left floating list element. Now, we will be able to adjust the width of the current-rating list element to how many stars is the average rating. The text-indent rule just moves the text off of the screen so that the user doesn’t see it anymore (an image replacement method). Last, but definitely not least is the z-index: 1 rule. This will cause the current rating to be at a z level of 1, basically the bottom of the stack. We have set the z-index of the a:hover state for the rating links to be at z-index:2. This causes the links to hover over the current rating image and that is exactly what we want. We want our rating to be visible over the current rating so that we can see what we are rating. Yeah, that makes sense.

Thats pretty much all of the CSS for the new current rating addition. We just have a few things left to cover. I mentioned that the image is a three state image so we had to change some of the CSS in the previous tutorial. Basically, and CSS rules declared that use the background now have to be changed. First, we have to change the CSS delclaration for the main star-rating unordered list:

  1. .star-rating{
  2. background: url(star_rating.gif) top left repeat-x;
  3. }

Here, we just merely changed the background position on the y-axis to be at the top. That way, initially you will see the unrated star. Perfect. On to the next declaration. The next declaration we have to change is the CSS declaration for the hover state for the rating links:

  1. .star-rating li a:hover{
  2. background: url(star_rating.gif) left center;
  3. }

Once again this will be an easy change. Here, we will change the active rating state to the center image. So when the user hovers the rater, they will see the vertically centered image as hover image. Neato.

The very last thing I want to mention is how to change the current rating. I showed it in the examples above, but here is the final word. Check out this code snippet to see how I did it:

  1. <ul class=’star-rating’>
  2. <li class=’current-rating’ style=’width:105px;’>
    Currently 3.5/5 Stars.
    </li>
  3. <li>
    <a href=’#’ title=’1 star out of 5′ class=’one-star’>
    1 star
    </a>
    </li>
  4. <li>
    <a href=’#’ title=’2 stars out of 5′ class=’two-stars’>
    2 stars
    </a>
    </li>
  5. <li>
    <a href=’#’ title=’3 stars out of 5′ class=’three-stars’>
    3 stars
    </a>
    </li>
  6. <li>
    <a href=’#’ title=’4 stars out of 5′ class=’four-stars’>
    4 stars
    </a>
    </li>
  7. <li>

    <a href=’#’ title=’5 stars out of 5′ class=’five-stars’>
    5 stars
    </a>
    </li>

  8. </ul>

The bold line is the only line you will have to change to make the rater show what current rating it has. I decided to include it as an in-tag style because its easier to accomplish with server-side scripting. The other solution that I had was to id every current-rating list element and then in an inline stylesheet I declared all the values there. It’s your call.

The only thing you’ll need here is a little math. Remember, each star is 30 pixels wide. So, I’m sure that you will have a server-side script running to determine the average rating for the current item/article, so lets just pretend that the script figured that the average rating was 3.5 stars. Here’s the solution:

Average Rating: 3.5
Each Star Width: 30px;
Set width to: 3.5 * 30 = 105px

So, in this case you will set the list element with a class of current-rating to a width of 105px. Thats it!

Here are some samples of two different rating systems I set up, each including the CSS and the XHTML code to accomplish it:

Want to know how to implement this system with PHP and a Database? Over at SLIM, there is a great tutorial written on just this article.

Comments

217 Comments

Pages:
  1. Ben Nowacky said 2704 days ago

    I used a version of this for a site for a client… I did some mods to it, but you can see how it’s been implemented on one of the regional sites … http://www.localrunning.com/competitor/rotm.php

    Just click on any of the individual runs, and you can post comments, and vote… voting is using a version of the star rating system,

  2. j0k3r said 2704 days ago

    I don’t understand why phpclasses.org take again this system without quote you!!!

    > http://www.phpclasses.org/browse/package/2838/

    o_O

  3. dayve said 2706 days ago

    Thanks… I finally finished the AJAX version tonight. I am very pleased with the end results.

  4. Rogie said 2707 days ago

    dayve. freakin’ killer. i love to see this stuff get out and on the web. way to go!

  5. dayve said 2707 days ago

    Great Job! I implemented this at my site for members to rate the songs that are submitted via the Now Playing feature we offer. Members can now view a community recent playlist and vote. Next step is to use AJAX for a more dynamic feel.

    http://www.burningsoulsforum.com/forum/statistics_winamp_member.asp?member=-1&view=1

    Thanks again!

  6. Rogie said 2708 days ago

    hugo,
    by semantic, I mean using a list element, NOT divs. Since I haven’t seen your XHTML, and you mentioned divs, I assumed maybe, just maybe they were a bunch of divs. Nesting is fine, but the display in legacy browsers would probably seem wierd, especially with all that indenting of sublists.

    Also, hugo, never, ever joke about NOT supporting IE. I am sure that we would love to support IE till our dying day….or its. Man, I hope IE dies. :)

  7. Hugo Wetterberg said 2708 days ago

    rogie,
    Well, yes I know, bad joke, it can’t really be used if it doesn’t support IE.

    As to not being semantically correct, isn’t that really just a matter of opinion? Or am I – god forbid – missing something here? Because it is possible to argue the list isn’t sematically correct either, as it suggests that the user gives the raing of star number X instead of X stars. I belive nesting to be the most correct representation. If you select B in a list [A,B,C,D] then B is the only thing that you have selected. In a structure with nested lists containing the elements [A[B[C[D]]]] selecting B means that you have selected [A,B]. But using nested ul:s results in very ugly markup. I think that I will go with the div:s in this case, until I’m allowed to use custom elements as rating and star.

  8. Rogie said 2709 days ago

    hugo,

    A few problems here. all divs is not semantically correct XHTML. It has no meaning, except a bunch of wrappers (see DIVitis). Another thing, who cares about IE support? I do. ;) Not to be a stickler, but I do web design. My clients want to reach others and usually they want to reach as many people as possible. That means IE really does matter when it roughly 61% of all people are using it.

  9. Hugo Wetterberg said 2709 days ago

    Well, no divs, the html-code was stripped out, should’ve been five nested divs where the top div had the class “starRating”.

  10. Hugo Wetterberg said 2709 days ago

    Nice one, I came to think of an alternate solution that works for an arbitrary number of stars:

    .starRating, .starRating div{
    height: 20px;
    background-image:url(img/star_rating.gif);
    background-position:top left;
    background-repeat:no-repeat;
    padding-left:20px;
    cursor:pointer;
    }
    .starRating:hover, .starRating div:hover{
    background-position:bottom left;
    }

    No links, but you can always hook it up with javascript instead.

    PS.
    Who cares about IE support :)

  11. Aaron Zercher » Blog Archive » CSS Star Rating System, Part 2 said 2709 days ago

    [...] em using only CSS and a list of links and default average results (including half-values). read more | digg story This entry was posted on Wednesda [...]

  12. ZonaPHP » Crear un sistema de Rating con CSS, PHP y MySQL said 2711 days ago

    [...] algo muy “web 2.0″, tan de moda ??ltimamente. La gente de Komodomedia public?? un tutorial explicando como lograr este efecto, utilizando CSS y una [...]

  13. Yvo Schaap said 2711 days ago

    A short guide (with all files) on how to do it this with AJAX: http://www.yvoschaap.com/index.php/weblog/css_star_rater_ajax_version/

  14. Rogie said 2712 days ago

    Good work Ryan and Jon! Guys, I don’t mind at all if you post here. This is how we web designers get stuff done. I am glad to see that you guys have taken this to the next level. I would really like to see a wordpress plugin out of this :)

  15. ryan said 2712 days ago

    I think I solved both my points above. You can see the multiple rating bars here: http://www.masuga.com/thelab/ajaxrate/

    My thought with multiples on a page is to make a Wordpress plugin similar to Votio ( but better :) ).

    If anyone wants to see what I’ve done and take it further, or just streamline what’s there, I’m at ryan at masuga dot com.

  16. ryan said 2713 days ago

    Jon – Awesome work!

    I’ve taken your files and modified them a bit (made it a 10 star system, renamed all ’star’ references to ‘unit’ so that someone using this can use any ‘unit’ they want without getting confused :), and also used a loop to generate the li’s to help simplify dropping multiple starbars onto a page) but I had a couple questions. (Rogie – sorry to put all this here, but I don’t know how to get a hold of Jon directly)

    1. How can I put more than one of those rating bars on a page? I made a test page with four starbars on it. I gave them different ID’s, which is fine for writing to the DB, but if I reload the page (I’ve turned off IP checking while testing…) all four show the value of the first starbar on the page, even though they really have different values in the db. THe only way I can see their real values is to vote on them again. Somehow (I guess at page load) I need to maybe see all the star-rating ID’s on the page, loop that db query and look for the matching id, and then pass the voting total for each id back to the page.

    2. Would it be easy change this rating system to check if an ID exists when voting…and if it does, just update the right record, and if it doesn’t, to Insert that new ID into the db? I honestly tried doing this but each starbar was getting stuck on the “Loading…” message. This way, I can drop a new starbar on a page with a fresh id (maybe getting its id from a blog post id or something) and if it doesn’t exist already, then it will when someone votes on it for the first time. I’m basically looking for a way not to have to seed a new id in the db.

    Thanks again for your work (and of course yours, Rogie). And also Slim Design.

  17. jon said 2713 days ago

    for people who migh want this ajaxified, here a version i came up with:
    http://h1.ripway.com/LHS_Webmaster/Storage/AJAX_RATE.zip

  18. live website creation and promotion » Blog Archive » Ratings said 2713 days ago

    [...] ibris Ratings Added ratings to MyFilmz. All credits are going to Rogie King for his very nice CSS star rating code. Right now you can [...]

  19. ryan said 2713 days ago

    This is awesome. I can’t imagine it would be too difficult to tie this in with some AJAX – similar to what happens when you Digg something over at Digg. It updates the count right there and disallows you from digging again. This Would be a great solution for me if it had that capability. I think I might get with my co-worker on this to see if we can’t some up with something. Thanks for taking the time to post these articles.

  20. Roshan.info said 2714 days ago

    links for 2006-01-13

    CSS Star Rating Part Deux

  21. Ivan Minic said 2714 days ago

    This is simply brilliant! :)

  22. Rogie said 2714 days ago

    thanks andy for the tip. I hope that will take care of it. And now for timg. Here you go fella:

    Vertical star rating system

    Enjoy. :)

  23. kc said 2714 days ago

    This is fantastic. Thanks!

  24. Echilon said 2714 days ago

    I really like this. I might have a go at implimenting it over the weekend.

  25. Andy Beeching said 2714 days ago

    Nice technique, like Trovster pointed out above, you need to get rid of the halo effect in FF. This article might help:

    http://sonspring.com/journal/removing-dotted-links

    as overflow: hidden didn’t for me.

  26. timg said 2714 days ago

    Has anyone mad a vertical rater like this?

  27. Linkdump van 13 januari 2006 | el73 said 2715 days ago

    [...] januari 2006 – Lees de reacties Onderwerpen: linkdump CSS Star Rating Part Deux Sterren uitdelen. (tags: css javascript web [...]

  28. david said 2715 days ago

    Show me some love guys! lol check out the php implementation of this rating system http://slim.climaxdesigns.com

  29. Rogie said 2715 days ago

    mikey. the only thing i can think of as of now would be a cookie solution. that way when any user visited/re-visited an item/article with a rating, they would see their rating pulled up from a cookie. I guess that would be pretty easy. Just cookie the id of the item and the rating. Then when the browser loads, check for that cookie for that item and load the rating appropriately. Unfortunately, that means the user can only see their rating, which may have its applications, but I believe that the average rating from many users has much more application on the web. :)

  30. mikey said 2715 days ago

    What about getting it to stick w/o submitting it to a DB?

  31. Rogie said 2715 days ago

    Thanks to all for the kind comments. They keep me inspired to do more work like this. After all, I do have more stuff like this lurking in my mind that I’d like to get out into tutorial form.

    Also, good work mooz. I love when other designers can use anything that I can give and rework it into something great.

  32. Tim Linden said 2715 days ago

    I like it. Alot.

  33. Cheyne said 2715 days ago

    Great work. If only I had somewhere I can implement this :)

    You have been blogged on http://thewebdesignblog.com

  34. The Web Design Blog - said 2715 days ago

    [...] 12, 2006 CSS star rating part deux Filed under: CSS — Cheyne @ 9:25 am Create a 5 star rating system, including half-values using CSS. Just when you [...]

  35. trovster said 2715 days ago

    Oh, I’ve “dugg” it by the way… http://digg.com/programming/CSS_Star_Rating_System,_Part_2

  36. trovster said 2715 days ago

    This is extremely nice. Well done. Only quibble is that it needs overflow: hidden; adding, to stop the halo effect in Firefox1.5.

    I’ll definitely be adding this to my new site’s backend, so I can quickly rate films I’ve watched. Infact, I was thinking about it last night, and half-scores… Is there a facility to RATE half-scores, like the average…

  37. mooz said 2715 days ago

    Excellent idea Rogie, and you gave me the inspiration to redux the rater I made a couple of months ago. ( http://robarov.be/rate/ )

    Redux version: http://robarov.be/rate2/

    Thanks for another great tuto!

  38. randy said 2715 days ago

    Wow this is such a great post! I had no idea you could create a star rating system with CSS. I just ordered Bullet Proof Web Design from Amazon so hopefully I can learn more cool things like this.

  39. davidbisset.com » CSS Star Rating Part Deux said 2716 days ago

    [...]

    davidbisset.com

    CSS Star Rating Part Deux Improvement on the creation of a 5-star rating system using only CSS and [...]

  40. bradleyD said 2716 days ago

    Wow, a great improvement upon a brilliant first tutorial!

    Well done and thanks!

  41. mayvelous said 2716 days ago

    Cute stars and a great article, definitely add to my reference lists.
    Thank you.

  42. Sausage said 2716 days ago

    Fantastic! I love this system!
    Now looking for an application to use this on. Thanks a lot!

  43. rogie said 2716 days ago

    jon, when you get done with that ajax, do you mind throwing that code my way? thanks a ton!

  44. jon said 2716 days ago

    just beautiful.
    i’m trying to incorporate this with ajax too!

  45. Zeerus said 2716 days ago

    great job Rogie, this is what I’ve been waiting for. Thanks to David’s PHP, this is a great little rating system going here.

  46. Vesa Virlander said 2716 days ago

    Good to see this update on the awesome star rating tutorial. Have to test this new method now.

  47. david said 2717 days ago

    D=> I might a little biased here ;) buti believe the average is what we want. we are not asking for an ‘either or’ based on the rating we want to know what the ‘average response’ is.

    having said that, it took me all of 15 minutes to implement this and carry it out in the php system over on slim.climaxdesigns.com
    give me until tomorrow to get the updated tutorial up. I might even separate it into another tut just to show what was changed to suit.

    meanwhile you can take a look at it live in action over on the prior mentioned site

  48. D said 2717 days ago

    You might consider using the median instead of the average.

  49. timg said 2717 days ago

    No matter what I do, the rater jumps the first time I hover over it or resize the window. This messes up my layout. How can this be fixed?

  50. timg said 2717 days ago

    Good article!

Sorry, the comment form is closed at this time.