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:

Step 4: The CSS, the Magic
- .star-rating li.current-rating{
- background: url(star_rating.gif) left bottom;
- position: absolute;
- height: 30px;
- display: block;
- text-indent: -9000px;
- z-index: 1;
- }
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:
- .star-rating{
- …
- background: url(star_rating.gif) top left repeat-x;
- }
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:
- .star-rating li a:hover{
- background: url(star_rating.gif) left center;
- …
- }
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:
- <ul class=’star-rating’>
-
<li class=’current-rating’ style=’width:105px;’>
Currently 3.5/5 Stars.
</li> - <li>
<a href=’#’ title=’1 star out of 5′ class=’one-star’>
1 star
</a>
</li> - <li>
<a href=’#’ title=’2 stars out of 5′ class=’two-stars’>
2 stars
</a>
</li> - <li>
<a href=’#’ title=’3 stars out of 5′ class=’three-stars’>
3 stars
</a>
</li> - <li>
<a href=’#’ title=’4 stars out of 5′ class=’four-stars’>
4 stars
</a>
</li> - <li>
<a href=’#’ title=’5 stars out of 5′ class=’five-stars’>
5 stars
</a>
</li> - </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:
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:
- Example 1: 150 x 30 star rating system
- Example 2: 125 x 25 star rating system
- Example 3: 25 x 125 vertical star rating system
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.




217 Comments