Back to Writing

jQuery Star Comment Rating

A flexible and animated star rating component built with jQuery, featuring a rollover effect and edit mode.

Eli Geske 13 min read
jquery star-rating ui animation javascript css

This tutorial walks through creating a nice little rating effect using jQuery. It includes the JavaScript, HTML, CSS, and basic image structure needed to build a functional star rating component.

jQuery Star Rating Preview

Overview

The rating system consists of three main parts:

  1. Rating Buttons: The interactive area where users hover and click.
  2. Rating On: The visual representation of the current hover/selected state.
  3. Rated State: The “frozen” state shown after a user has made a selection.

File Structure

The project starts with:

  • star_rating.html
  • jquery-1.3.2.min.js
  • star_rating.js
  • images/ folder containing star assets
jQuery Star Rating Project File Structure

The HTML

The core container holds the buttons, the “on” state div, and the final rated display.

<div id="rating_cont">
  <div id="rating_btns">
    <ul>
      <li>0.5</li>
      <li>1.0</li>
      <li>1.5</li>
      <li>2.0</li>
      <li>2.5</li>
      <li>3.0</li>
      <li>3.5</li>
      <li>4.0</li>
      <li>4.5</li>
      <li>5.0</li>
    </ul>
  </div>
  <div id="rating_on">&nbsp;</div>
  <div id="rated">
    <div id="rating" style="height: 17px; line-height: 17px;">not rated</div>
    <div>– &nbsp;</div>
    <div id="small_stars">&nbsp;</div>
    <div id="rate_edit">edit</div>
  </div>
</div>
<input
  type="hidden"
  id="rating_output"
  name="rating_output"
  value="not rated"
/>

The CSS

The trick here is using z-index and relative positioning. The buttons sit on top (z-index: 100) while the “on” stars sit below them (z-index: 50).

#rating_cont {
  background: #1e1d1c url(images/rating_background.jpg) top left no-repeat;
  border: 1px solid #f9ba0d;
  width: 140px;
  height: 23px;
  text-align: left;
  margin-left: 6px;
}

#rating_btns {
  position: relative;
  z-index: 100;
  width: 140px;
  height: 21px;
}

#rating_btns ul,
#rating_btns li {
  padding: 0;
  margin: 0;
}

#rating_btns li {
  float: left;
  width: 14px;
  height: 21px;
  display: block;
  font-size: 1px;
  cursor: pointer;
  color: #1e1d1c;
}

#rating_on {
  background: url(images/rating_onbackground.jpg) top left no-repeat;
  width: 0px;
  height: 21px;
  position: relative;
  z-index: 50;
  top: -21px;
}

#rated {
  display: none;
  width: 138px;
  padding: 3px 0px 3px 2px;
  height: 23px;
  background-color: #1e1d1c;
  height: 17px;
  font-size: 11px;
  color: #ffc910;
}

#rated div {
  display: block;
  float: left;
}

#rating {
  font-size: 11px;
  font-family: Arial, Helvetica, sans-serif;
  color: #ffc910;
  padding-left: 3px;
  width: 22px;
}

#small_stars {
  height: 11px;
  width: 69px;
  background-image: url(images/stars_small_sprite.jpg);
  background-position: 0px -11px;
  font-size: 1px;
  line-height: 11px;
  margin-top: 3px;
}

#rate_edit {
  line-height: 17px;
  font-size: 11px;
  font-family: Arial, Helvetica, sans-serif;
  color: #fff;
  padding-left: 9px;
  cursor: pointer;
}

#rate_edit:hover {
  text-decoration: underline;
}

The jQuery

The logic handles the hover transitions, clicking to lock in a rating, and an edit mode to reset the state.

$(document).ready(function () {
  // hover
  $('#rating_btns li').hover(function () {
    $rating = $(this).text()
    $('#rating_on').css('width', rateWidth($rating))
  })

  // mouseout
  $('#rating_btns li').mouseout(function () {
    $rating = $('#rating').text()
    if ($rating == 'not rated') {
      $('#rating_on').css('width', '0px')
    } else {
      $('#rating_on').css('width', rateWidth($rating))
    }
  })

  // click
  $('#rating_btns li').click(function () {
    $rating = $(this).text()
    $('#rating').text($rating)
    $('#rating_output').val($rating)
    $pos = starSprite($rating)
    $('#small_stars').css('background-position', '0px ' + $pos)
    $('#rating_btns').hide()
    $('#rating_on').hide()
    $('#rated').fadeIn()
  })

  // edit
  $('#rate_edit').click(function () {
    $('#rated').hide()
    $('#rating_btns').fadeIn()
    $('#rating_on').fadeIn()
  })

  function rateWidth($rating) {
    $rating = parseFloat($rating)
    switch ($rating) {
      case 0.5:
        return '14px'
      case 1.0:
        return '28px'
      case 1.5:
        return '42px'
      case 2.0:
        return '56px'
      case 2.5:
        return '70px'
      case 3.0:
        return '84px'
      case 3.5:
        return '98px'
      case 4.0:
        return '112px'
      case 4.5:
        return '126px'
      case 5.0:
        return '140px'
      default:
        return '84px'
    }
  }

  function starSprite($rating) {
    $rating = parseFloat($rating)
    switch ($rating) {
      case 0.5:
        return '-11px'
      case 1.0:
        return '-22px'
      case 1.5:
        return '-33px'
      case 2.0:
        return '-44px'
      case 2.5:
        return '-55px'
      case 3.0:
        return '-66px'
      case 3.5:
        return '-77px'
      case 4.0:
        return '-88px'
      case 4.5:
        return '-99px'
      case 5.0:
        return '-110px'
      default:
        return '-77px'
    }
  }
})

Legacy Archive

[The original post as it appeared on eligeske.com in 2009]

UPDATE!! A plugin is now available for this tutorial that includes more features, like a new theme and number of stars options!

Here is a nice little rating effect. This does not include the PHP, it is only the JavaScript, HTML, CSS, and Images. If you like this, I do have the PHP script that I created, but will not support, and I threw together quite quickly. But, what the heck, back to this post now.

Look below and you can see what will be created by the time we are done with this project.

Full Source Code

HTML (star_rating.html)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>JQuery-Star Comment Rating</title>
    <script type="text/javascript" src="js/jquery/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="js/star_rating.js"></script>
    <style type="text/css">
      #rating_cont {
        background: #1e1d1c url(images/rating_background.jpg) top left no-repeat;
        border: 1px solid #f9ba0d;
        width: 140px;
        height: 23px;
        text-align: left;
        margin-left: 6px;
      }
      #rating_on {
        background: url(images/rating_onbackground.jpg) top left no-repeat;
        width: 0px;
        height: 21px;
        position: relative;
        z-index: 50;
        top: -21px;
      }
      #rated {
        display: none;
        width: 138px;
        padding: 3px 0px 3px 2px;
        height: 23px;
        background-color: #1e1d1c;
        height: 17px;
        font-size: 11px;
        color: #ffc910;
      }
      #rated div {
        display: block;
        float: left;
      }
      #rating {
        font-size: 11px;
        font-family: Arial, Helvetica, sans-serif;
        color: #ffc910;
        padding-left: 3px;
        width: 22px;
      }
      #small_stars {
        height: 11px;
        width: 69px;
        background-image: url(images/stars_small_sprite.jpg);
        background-position: 0px -11px;
        font-size: 1px;
        line-height: 11px;
        margin-top: 3px;
      }
      #rate_edit {
        line-height: 17px;
        font-size: 11px;
        font-family: Arial, Helvetica, sans-serif;
        color: #fff;
        padding-left: 9px;
        cursor: pointer;
      }
      #rate_edit:hover {
        text-decoration: underline;
      }
      #rating_btns {
        position: relative;
        z-index: 100;
        width: 140px;
        height: 21px;
      }
      #rating_btns ul,
      #rating_btns li {
        padding: 0;
        margin: 0;
      }
      #rating_btns li {
        float: left;
        width: 14px;
        height: 21px;
        display: block;
        font-size: 1px;
        cursor: pointer;
        color: #1e1d1c;
      }
    </style>
  </head>
  <body>
    <div id="rating_cont">
      <div id="rating_btns">
        <ul>
          <li>0.5</li>
          <li>1.0</li>
          <li>1.5</li>
          <li>2.0</li>
          <li>2.5</li>
          <li>3.0</li>
          <li>3.5</li>
          <li>4.0</li>
          <li>4.5</li>
          <li>5.0</li>
        </ul>
      </div>
      <div id="rating_on">&nbsp;</div>
      <div id="rated">
        <div id="rating" style="height: 17px; line-height: 17px;">
          not rated
        </div>
        <div>– &nbsp;</div>
        <div id="small_stars">&nbsp;</div>
        <div id="rate_edit">edit</div>
      </div>
    </div>
    <input type="hidden" id="rating_output" name="rating_output" />
  </body>
</html>

JQuery/JavaScript (star_rating.js)

/*
 * Written by eligeske
 * downloaded from eligeske.com
 * have fun. nerd.
 */
$(document).ready(function () {
  // hover
  $('#rating_btns li').hover(function () {
    $rating = $(this).text()
    $('#rating_on').css('width', rateWidth($rating))
  })
  // mouseout
  $('#rating_btns li').mouseout(function () {
    $rating = $('#rating').text()
    if ($rating == 'not rated') {
      $('#rating_on').css('width', '0px')
    } else {
      $('#rating_on').css('width', rateWidth($rating))
    }
  })
  //click
  $('#rating_btns li').click(function () {
    $rating = $(this).text()
    $('#rating').text($rating)
    $('#rating_output').val($rating)
    $pos = starSprite($rating)
    $('#small_stars').css('background-position', '0px ' + $pos)
    $('#rating_btns').hide()
    $('#rating_on').hide()
    $('#rated').fadeIn()
  })
  //edit
  $('#rate_edit').click(function () {
    $('#rated').hide()
    $('#rating_btns').fadeIn()
    $('#rating_on').fadeIn()
  })
  function rateWidth($rating) {
    $rating = parseFloat($rating)
    switch ($rating) {
      case 0.5:
        $width = '14px'
        break
      case 1.0:
        $width = '28px'
        break
      case 1.5:
        $width = '42px'
        break
      case 2.0:
        $width = '56px'
        break
      case 2.5:
        $width = '70px'
        break
      case 3.0:
        $width = '84px'
        break
      case 3.5:
        $width = '98px'
        break
      case 4.0:
        $width = '112px'
        break
      case 4.5:
        $width = '126px'
        break
      case 5.0:
        $width = '140px'
        break
      default:
        $width = '84px'
    }
    return $width
  }
  function starSprite($rating) {
    $rating = parseFloat($rating)
    switch ($rating) {
      case 0.5:
        $pos = '-11px'
        break
      case 1.0:
        $pos = '-22px'
        break
      case 1.5:
        $pos = '-33px'
        break
      case 2.0:
        $pos = '-44px'
        break
      case 2.5:
        $pos = '-55px'
        break
      case 3.0:
        $pos = '-66px'
        break
      case 3.5:
        $pos = '-77px'
        break
      case 4.0:
        $pos = '-88px'
        break
      case 4.5:
        $pos = '-99px'
        break
      case 5.0:
        $pos = '-110px'
        break
      default:
        $pos = '-77px'
    }
    return $pos
  }
})

Legacy Comments Archive

This post originally appeared on my old site and has been recovered from the archives. Below are the original comments from the community.

t
tt
November 9, 2009

too long

D
DH
November 13, 2009

well done! thanks for sharing!

e
eligeske Author
November 13, 2009

What makes it as lengthy as it appears is the rated box fade-in effect. If you need a shorter one you can take out the starSprite function, .click and the “edit”.click. Here is the edited Jquery that would only be the roll over effect:

$(document).ready(function(){
// hover
$(‘#rating_btns li’).hover(function(){
$rating = $(this).text();
$(‘#rating_on’).css(‘width’, rateWidth($rating));
});
// mouseout
$(‘#rating_btns li’).mouseout(function(){
$rating = $(‘#rating’).text();
if ($rating == “not rated”) {
$(‘#rating_on’).css(‘width’, “0px”);
}
else {
$(‘#rating_on’).css(‘width’, rateWidth($rating));
}
});
//click
$(‘#rating_btns li’).click(function(){
$rating = $(this).text();
$(‘#rating’).text($rating);
$(‘#rating_output’).val($rating);
});
function rateWidth($rating){
$rating = parseFloat($rating);
switch ($rating) {
case 0.5: $width = “14px”;break;
case 1.0:$width = “28px”;break;
case 1.5:$width = “42px”; break;
case 2.0:$width = “56px”;break;
case 2.5:$width = “70px”; break;
case 3.0:$width = “84px”; break;
case 3.5:$width = “98px”; break;
case 4.0: $width = “112px”;break;
case 4.5:$width = “126px”;break;
case 5.0:$width = “140px”;break;
default:$width = “84px”;
}
return $width;
}
});
S
Strawberry
November 15, 2009

Nice but when you reload the page it shows like you didn’t rate. So I do not see any purpose of this. :(

e
eligeske Author
November 15, 2009

Hey Strawberry,

This was created only to make a rating. You would need to add some server side scripting to this in order to make the rating stay. When creating a rating system you need to get the average of all the ratings on a particular item or post. Usually this is done by allowing the user to select which rating they want, then send it to the database, and have the average reappear.

Let me know a little bit about your skills so I can better assist you.

Are you a web designer or a programmer?

D
DJ
November 16, 2009

Thanks for the write-up. It works on firefox, but I notice that your page doesn’t render on chrome.

R
Rosie
November 22, 2009

That’s a cool code!

Love it!!!!

j
jay
December 1, 2009

You are great!!!!…i see it in every word……..keep going

m
me
December 1, 2009

Well its for every one ……… from the basic….i just installed it and was having trouble ..with file structure …you saved my day…thanks!!!!!

e
eligeske Author
December 1, 2009

Glad you found it helpful! Tis the season to be jolly! :P

K
Kakubei
December 5, 2009

This looks great,just what I need. But how would I pass the voted value to php since the page doesn’t seem to send a form? Also, could I build the chosen rating based on stored values

e
eligeske Author
December 5, 2009

Kakubei,

There are several different ways you could pass the vote into php. I’ll give you a couple examples.

  1. HTML form -
<form method="”your.php”" action="”post”">
  <input
    type="”hidden”"
    id="”rating_output”"
    name="”rating_output”"
    value="”not"
    rated”
  />
  <input type="”submit”" />
</form>

Note: The hidden input field that you created with the tutorial will have the value of the rating after they click it, so when they submit the form it will send the rating to your php file. Test it by changing the type=”hidden” to type=”text” and you can see how it works.

  1. AJAX (with JQuery of course) :) -
$url = ‘your.php’;
$rating = $(‘#rating_output’).val();
$.post($url, {
rating: $rating
}, function(data){
$(‘#rate_edit’).remove(); // hide the edit
});

Note: Put this right inside your $('#rating_btns li').click(function(){'{'} //here {'}'}); Also, notice inside the ajax function the .remove, this will remove the “edit” so they cannot send multiple ratings.

– Let me know if this has helped you at all. As far as the build the rating on stored values, explain what you are trying to do a little more on that and I ‘ll see what I can do.

Eli

A
AdamS
August 2, 2010

Hi,

Great script and it doesn’t interfere with my other jQuery scripts on the page. Took me a while to find one.

Question: Is there a way I can get it to default to a selection, in case the user makes a mistake on the form and I need to go back. i.e. defaults to 4 stars but they can then change their selection or maybe even turn off all the stars.

Thanks, Adam

e
eligeske Author
August 3, 2010

Ya, that shouldn’t be a problem at all.

Tell me step by step on how you are using it, or even better, show me an online example that your working on, if you have the ability.

A
AdamS
August 5, 2010

Eli is great!!! He helped me set a default value. Here is what you need to do:

Put your default value in the rating div and the hidden field: <div id=”rating”>2</div> <input type=”hidden” id=”rating_output” name=”rating_output” value=”2″ /> Note: you would place your session variable where the 2 is located i.e. <? echo $default_rating; ?>

Add the following above the //hover section in the .js file: // set default value $(‘#rating_on’).css(‘width’, rateWidth($(‘#rating_output’).val()));

In the rateWidth function, set the default to 0px: default: $width = “0px”;

That should do it. Again, thank you Eli for coming up with this great script. I searched a long time.

c
ct
October 17, 2010

this code working well so far but i’m trying to preload the values from database at start, i was able to use your additional ajax code to send to database, now i just want it to load from database at first showing the stored value in database. can you help

e
eligeske Author
October 17, 2010

Are you using php?

c
ct
October 25, 2010

yes i am using php and mysql

e
eligeske Author
October 29, 2010

<input id=”defaultValue” type=”hidden” value=”<?php echo $loadedValue; ?>” />

If you add a hidden input field and give it the value you have in your database as an initial value, then you can check it with jquery on page load to set the current rating.

Let me know if you have any questions on how to do this, I’ll be glad to help.

M
Michael
July 10, 2011

Hey ! I just absolutely love your rating system and would love to implement in on a website I have under development for a client. However, I would like it to average the user ratings and save this perhaps to a database ? Then I want this to be retrieved whenever a user visits the webpage for a image or item or something. Can you help me with that ?

I’m a programmer (HTML,CSS,JQuery, ASP.NET – C# and a bit of php).

  • Thanks
e
eligeske Author
July 10, 2011

Hi Michael,

There are many different ways to implement the server side portion of a rating system.

Here is a couple things to keep in mind:

  1. Keeping the same person from submitting multiple ratings on the same product.
  • allow only logged in users to submit rating.
  • track ratings by IP, which isn’t full proof but does the job.
  1. Is what is to be rated database driven itself? If so, then you would just add an additional table with a timestamp, rating, who rated it, and product id (or id of what you’re rating)
  2. Will need to expose some type of webservice or a page to catch the postback or get parameters from Ajax call when rating is clicked.

What program language will you be using?