site logoTune The Web
I've written a book! - click here to view or buy "HTTP/2 in Action" from Manning. Use code 39pollard to get 39% off!

CSS only Star Rating system

This page was originally created on and last edited on .


Many websites implement a Star Rating feedback system on their pages, where visitors can rate a page from 1 to 5 stars:

Star Rating Feedback System
Star Rating Feedback System
Star Rating Feedback System

This allows visitors to give valuable insight into which of your pages are useful and which could do with some improving. It can also help show you which topics are helpful which might help you decide on future pages to write.

You should implement analytics on your website, which will show which are your most popular pages, but a popular page may not be a useful one and people may read a page, think it was a complete waste of their time, and leave your website with a bad taste in their mouth never to return again.

Another useful feedback method is with a comment system (I use the popular Disqus commenting system on my pages), but a commenting system may not always be appropriate (e.g. for a company page) while a star rating system is a small subtle option that won't look out of place on most pages.

How to set it up

Implementing a star rating system is fairly simple. You just need to add 5 stars to your page and some CSS or Javascript to change the icon as your hover over them and react when you click on them.

It can be a little tricky to make all the stars "fill up", so that if you are hovering over the 3rd star than the 1st and 2nd stars are also filled up, so most implementations depend on Javascript to handle this. However I wanted to implement a CSS-only star rating system for a few reasons: 1) I'm not a fan of Javascript and think it's over used, 2) CSS now has the ability to do this natively without writing custom Javascript, 3) CSS solutions are usually more performant than Javascript ones and 4) They allow non-Javascript solutions like Accelerated Mobile Pages (AMP) to also have this.

So to implement this I nested 5 star buttons in overlapping spans (which will be important to allow the hover event to fall through to the underlying stars to give the fill up illusion). The HTML is shown below:

<section class="star-rating-section"> <h4>How useful was this page?</h4> <div id="star-rating"> <span class="star-rating star-rating-1"> <button id="star-rating-link-1">     </button> <span class="star-rating star-rating-2"> <button id="star-rating-link-2">     </button> <span class="star-rating star-rating-3"> <button id="star-rating-link-3">     </button> <span class="star-rating star-rating-4"> <button id="star-rating-link-4">     </button> <span class="star-rating star-rating-5"> <button id="star-rating-link-5">     </button> </span> </span> </span> </span> </span> </div> <span class="star-rating-example-desc"></span> <span id="star-rating-example-feedback-link" class="star-rating-feedback-link hidden">– Thanks for your feedback!</span> </section>

This is illustrated below:

Star Rating Stacking Divs

So if you hover over the third star span, then the hover event falls through and also activates the hover event on the first and second stars spans. Note that if we had used <a> anchor tags they would have swallowed up the hover event and so it would not fall through.

Additionally each div has a small button in the visible area which when clicked on will action the star rating. This could also be an <a> anchor tag but we don't want the click to make the page move anywhere so use <button>. Note also this requires overriding the default styling of buttons which we'll discuss next.

Then we need some CSS to style these, including using a background image to display the star, and the filled star on hover (I tried using inline SVGs but Firefox didn't seem to like them for some reason). We also set the widths to layer the stars on top of each other, and take off some of the default button stylings:

.star-rating { background-size: 20px; background-repeat: no-repeat; height: 20px; width: 20px; display: inline; background-image: url("/assets/images/star.svg"); } .star-rating:hover { background-image: url("/assets/images/star-filled.svg"); } .star-rating-1 { width: 100px; } .star-rating-2 { width: 80px; } .star-rating-3 { width: 60px; } .star-rating-4 { width: 40px; } .star-rating-5 { width: 20px; } .star-rating-link { border: none; color: transparent; background-color: transparent; padding: 2px; }

This gives a set of star rating icons which react nicely when you hover you mouse over them (though don't yet do anything when clicked on except set the default focus of your browser (usually add a light blue outline):

Now what you do when someone clicks on one of these ratings is up to you. You could take them to another page, log an event to your analytics system, or call a url via AJAX to feed back to your application server. I've also helped on implementations where a feedback form popped up afterwards with a small survey asking users to explain why they choose that rating with some simple standard questions ("Why did you visit the site today?", "Did you achieve what you wanted to do [Y/N]?" and "If you were not able to complete your task today then could you explain why not?").

I've decided to keep it simple and fire off an event to Google Analytics and then display a thank you message. Now this does require some javascript I admit so, despite the title of this page, my implementation isn't a 100% CSS only Star Rating System, but it could be if I wanted to use the links.

The easiest method to handle when the user clicks on the button is to use an onClick event. However I choose to use Event Listeners so I could pull this out to a separate Javascript file as I'm currently experimenting with Content Security Policy (aka CSP) so want to avoid inline javascript. This also allows me to use a slightly different call on my AMP pages, which I'll discuss more later. The Javascript I use is given here:

(function () { /* Add an Event Listener to each link.*/ document.getElementById('star-rating-link-1').addEventListener('click', function(){sendStarRating(1)}, false ); document.getElementById('star-rating-link-2').addEventListener('click', function(){sendStarRating(2)}, false ); document.getElementById('star-rating-link-3').addEventListener('click', function(){sendStarRating(3)}, false ); document.getElementById('star-rating-link-4').addEventListener('click', function(){sendStarRating(4)}, false ); document.getElementById('star-rating-link-5').addEventListener('click', function(){sendStarRating(5)}, false ); })(); /* Process the click by sending an event to Google Analytics, hiding the star ratings, and displaying the "Thank You" message instead. */ function sendStarRating(rating) { ga('send', 'event', 'Star Rating', location.pathname +, 'Rating: ' + rating, rating); document.getElementById('star-rating').style.display = 'none'; document.getElementById('star-rating-feedback-link').style.display = 'block'; };

In Google Analytics I can use the event screen to then view the results:

Google Analytics Custom Events For Star Ratings

For my AMP pages, I can use amp-analytics to send a similar event, using the same HTML and CSS as the normal page (though note in AMP we can't hide the star ratings and display the thank you message instead - though this should be possibly once amp-accordian moves out of experimental mode):

<amp-analytics type="googleanalytics" id="analytics1"> <script type="application/json"> { "vars": { "account": "UA-65113730-1" }, "triggers": { "track pageview": { "on": "visible", "request": "pageview" }, "trackStarRating1" : { "on": "click", "selector": "#star-rating-link-1", "request": "event", "vars": { "eventCategory": "Star Rating", "eventAction": "/usability/star-rating/amp/", "eventLabel": "Rating: 1", "eventValue": "1" } }, "trackStarRating2" : { "on": "click", "selector": "#star-rating-link-2", "request": "event", "vars": { "eventCategory": "Star Rating", "eventAction": "/usability/star-rating/amp/", "eventLabel": "Rating: 2", "eventValue": "2" } }, "trackStarRating3" : { "on": "click", "selector": "#star-rating-link-3", "request": "event", "vars": { "eventCategory": "Star Rating", "eventAction": "/usability/star-rating/amp/", "eventLabel": "Rating: 3", "eventValue": "3" } }, "trackStarRating4" : { "on": "click", "selector": "#star-rating-link-4", "request": "event", "vars": { "eventCategory": "Star Rating", "eventAction": "/usability/star-rating/amp/", "eventLabel": "Rating: 4", "eventValue": "4" } }, "trackStarRating5" : { "on": "click", "selector": "#star-rating-link-5", "request": "event", "vars": { "eventCategory": "Star Rating", "eventAction": "/usability/star-rating/amp/", "eventLabel": "Rating: 5", "eventValue": "5" } } } } </script> </amp-analytics>


I've tested the above in all major browsers (Chrome, Firefox, Opera, IE9-11, Edge, iOS and Android) and not seen any major issues. I've not done massive amounts of testing though so do let me know in the comments below if you spot an issue and will try to look into it.

The Downsides

One of the main downsides is time to set this up. While adding this to your pages should be fairly simple, having some backend system ready to process this could be an extra step but if you already have Google Analytics or something similar on your pages then you can just use this and not worry about this complex set up. Once it's set up it can quietly collect all the feedback in the background and you can analyse that data as you see fit.

Another thing to be aware of is the skew of this data. Most people will only bother to fill this in if they want to have a moan, or really like this page, so you usually end up with a lot of 1 star feedbacks or 5 star feedbacks, with less in between.

It's also important not to overreact to small sample sets and take on a huge piece of work to redesign your site simply because of one piece of feedback from someone who was potentially having a bad day!


A star rating system is simple to implement and can give good feedback on your website allowing you to continually improve your website. While most users will not bother to rate your pages, if your site gets any level of traffic then you will be surprised at the amount of feedback you get and how useful it might be.

This page was originally created on and last edited on .

How useful was this page?
Loading interactions…