Static Star Rating System

This post assumes basic understanding of CSS and website images.

Following the rule of separation of content and design, most web developers will limit any design element images to page's stylesheet. This includes repeating header, footer, logos, and body images. You can do some tricks with these images while linked to the stylesheet by utilizing the background-position style.

A block element (div, table, or forced by display:block) on a webpage can be thought of a window with information in it. The window's size depends on either the html content within it or the CSS declared height and width. When you have a background image from your stylesheet for a block element, the div will not change its shape to fit the image. Instead, if the image is larger than the window, part of the image will be hidden. You can control what is visible by changing the background-position to force the image to float to a certain side (left v right and top v bottom) or specify how far to the left and top in pixels the image should appear.

Why is this useful? Well, it takes time for images to download on your visitor's computer, and some images may be automatically cached by their browser. If you used a single image for your star rater, then they only have to download one image to view all of the ratings, no matter how many stars are lit up for any particular rating. Below is an example of the image I used on my waterfall site.

The first step is creating the html for each rating. In my case, I had a backing database with a number between 0 and 9, 9 being the highest with the most 'stars'. After doing a query, usually based on the waterfall name, to retrieve this number, I made a php function to make the html generation easier.

  1. /*Displays stars*/

  2. function rater($value) {

  3. echo '<span class="rate'.$value.' stars"><span class="hidden">'.$value.'</span></span>';

  4. }

The PHP side of this is fairly obvious - given a specific value, a span is generated with the appropriate class name. Also, the rating is displayed, but within a hidden span. With CSS disabled, this number shows up normally - else, the CSS hides the number and displays an image defined by the outer span. For example, if you feed this function a value of 4, it would output:

  1. <span class="rate4"><span class="hidden">4</span></span>

This is optional - you may just have the html static.

The next step is setting up the css to handle the different ratings. First is the stars class - which all ratings will have.

  1. .stars {

  2. background: url('http://www.jacobemerick.com/waterfalls/images/stars.png') no-repeat;

  3. display: block;

  4. height: 20px;

  5. overflow: hidden;}

This not only links all of the ratings to the same image, but it sets the height to the star's height (20 px) and keeps the rest of the image hidden with overflow property. If we were to keep the CSS to this, then each image would have to the uppermost set of stars - the 0 rating, or 1/2 a star in my case. Next we have to set each rating class to a different background position.

  1. .rate0 {

  2. background-position: 0 0;}

  3. .rate1 {

  4. background-position: 0 -20px;}

  5. .rate2 {

  6. background-position: 0 -40px;}

  7. .rate3 {

  8. background-position: 0 -60px;}

  9. .rate4 {

  10. background-position: 0 -80px;}

  11. .rate5 {

  12. background-position: 0 -100px;}

  13. .rate6 {

  14. background-position: 0 -120px;}

  15. .rate7 {

  16. background-position: 0 -140px;}

  17. .rate8 {

  18. background-position: 0 -160px;}

  19. .rate9 {

  20. background-position: 0 -180px;}

Since each row of stars is 20px high, each rating moves the image up 20px to display the next row. The first 0 in each row is simply the x-value, which is also left-aligned.

The one piece I left out was the width of the display. If this isn't specified, then the display:block property will give the span a width of 0, collapsing the span and hiding any image contained within. This is because I used the technique on both definition list (dl) and paragraph (p) tags, both of which had different width and layout requirements. A simple width:106px on the star class would fix this.