Accessible star rating widget with pure CSS

For ages, we couldn’t utilize the sibling combinators (~ and +) to ease the pain of creating star rating widgets, because of this stupid Webkit bug. Nowadays, not only it’s fixed, but the fix has already propagated to Chrome and Safari 5.1. So, we can at least use the sibling combinator to make coloring the stars easier.

But can we use no JavaScript for a rating widget and make it just with CSS?

Actually, we can. By adapting Ryan Seddon’s technique for custom radio buttons with CSS, we can turn a series of radio buttons into stars that change colors (for the purposes of this demo they’re just unicode characters that change colors, but in your case they may as well be images) and use the sibling combinator to color the previous stars. A series of radio buttons is what many people use as a star rating widget fallback anyway, so the markup required is not necessarily more than usual. The only thing that needs to be done differently is their reverse ordering: The highest ratings need to go first, due to the way CSS3 selectors work (this limitation might be removed in CSS4, but that’s a long way ahead).

Of course, you’d still need JS to attach an event handler if you want the votes to be registered through AJAX, but that’s not part of the rating widget per se (it could still work as part of a regular form).

What’s best is that it’s fully keyboard accessible (focus and then use keyboard arrows) and screen reader accessible (although VoiceOver will also pronounce the generated stars, but that won’t happen if you use images instead of unicode stars). I’m guessing it could become even more accessible with proper ARIA, but I’ll leave that as an exercise to the commenter :D

In browsers that don’t support :checked (essentially only IE < 9), it degrades to a series of radio buttons (haven’t verified that it does, but it should do).

So, here it is:

  • http://jiffdesign.de/ sascha fuchs

    Nice Technique i used it for my next project. Thanks 

  • http://twitter.com/arrutime José Luis Arruti

    It’s awesome, thx

  • http://twitter.com/czarodziejmarx Mark Gubiec

    @LeaVerou:twitter  “(for the purposes of this demo they’re just unicode characters that change colors, but in your case they may as well be images)” – or we could use a gradient pattern :D from your gradient patterns gallery :D I can’t believe Gradient Queen forgot to mention using gradients here :>

    • http://leaverou.me Lea Verou

      Have you seen how much code a gradient needs to generate a star? Use everything where it helps. In this case, gradients won’t help anyone.

  • http://bowdenweb.com/ J. Albert Bowden II

    you have seriously been pumping out hardcore webdev awesomeness! nicely done! you should consider offering it up as the universal Linked Open Data Star Scheme example. seriously, nicely done!

  • http://allyoucanleet.com John-David Dalton

    In browsers that don’t support :checked (essentially only IE < 9), it degrades to a series of radio buttons (haven’t verified that it does, but it should do).

    I noticed it behave oddly in Chrome and IE8:

    • http://leaverou.me Lea Verou

      Chrome 12 is old and probably still has the Webkit bug I mentioned (that’s how it looks). I have Chrome 13, and I’m not in any dev channel, so my guess is you need to update your Chrome.

      As for the IE8, I think I fixed it, but the change will take a while (around an hour usually) to propagate to the embedded fiddle.

      • http://allyoucanleet.com John-David Dalton

        Chrome 12 is old and probably still has the Webkit bug I mentioned (that’s how it looks). I have Chrome 13, and I’m not in any dev channel, so my guess is you need to update your Chrome.

        Ah good to know, will add v13 to my browser collection. I gotta say I am not a fan of catering to only super new browsers (in this case Chrome 13th is like 9 days old and Safari 5.1). I would dig something that’s a bit more robust or even falls back to the plain radio buttons if the full non-buggy effect cannot be achieved. Also I noticed this star effect makes a rating system unusable on my iPhone 3GS *(iOS 3.1.3)* because I can’t select a star (plain radio buttons would work though).

        As for the IE8, I think I fixed it, but the change will take a while (around an hour usually) to propagate to the embedded fiddle.

        Yap IE 8 works better now. The added not(:checked) did the trick.

        • http://leaverou.me Lea Verou

          Chrome updates so fast that in a few days Chrome 12 won’t be an issue any more.  In a few weeks, I’d argue that Safari 5 won’t be an issue either.

          I noticed the iPhone bug myself too a few hours ago, but I’m not sure if it’s actually an issue of this demo or another jsFiddle bug (as jsFiddle doesn’t support Mobile Safari).

        • http://allyoucanleet.com John-David Dalton

          Chrome updates so fast that in a few days Chrome 12 won’t be an issue any more.  In a few weeks, I’d argue that Safari 5 won’t be an issue either.

          I see where you are coming from but I don’t agree with it. I think that since this star layer is bonus it shouldn’t affect its functionality. We don’t know how fast other users will update their browsers/devices (that use WebKit). I prefer to play it safe and go for the biggest compatibility win.

          I noticed the iPhone bug myself too a few hours ago, but I’m not sure if it’s actually an issue of this demo or another jsFiddle bug (as jsFiddle doesn’t support Mobile Safari).

          It’s a problem with your demo. Visit the /show page to test.

        • http://leaverou.me Lea Verou

          You can argue about Safari, but not about Chrome. Chrome autoupdates, so in less than 2 months, practically EVERYONE has the new version. Also, the hover effect can hardly be considered “functionality”.  Its functionality is intact: The correct radio button gets checked.

          I should look into the Mobile Safari issue though.

        • http://allyoucanleet.com John-David Dalton

          You can argue about Safari, but not about Chrome. Chrome autoupdates, so in less than 2 months, practically EVERYONE has the new version. 

          Android devices ship with Chrome or Chrome-like browsers. I know desktop Chrome auto-updates but I am not sure about other platforms.

        • http://leaverou.me Lea Verou

          Good point.

          Well, I guess if you want to be super safe, you can wrap the whole thing in a media query that only applies to desktop browsers. This way you probably won’t need the :not(:checked) filter either. :)

        • Arvind Mehra

          Your rating system is awesome but it shows simple radio buttons in IE versions (I hope you know that) and my boss doesnt wants it that way so could you pls suggest me an altenative asap.
          BTW Kudos I have seen you posts you are incredible in this field.

        • http://lea.verou.me/ Lea Verou

          It only shows radio buttons in IE8, which is 15% at most (and even less for certain target groups). It should work fine in IE9 and after.

  • http://twitter.com/thierrykoblentz Thierry

    I’ve done something a bit similar, relying on some JS though to make it work in IE6/7 too:
    http://www.yuiblog.com/blog/2010/08/24/developing-an-accessible-star-ratings-widget/

    • http://twitter.com/jitendravyas Jitendra Vyas

      Hmm very good. but both yours and Lea doesn’t have the option of half selection. like if i want to give 3.5 star.

      • ceecore

        That would be almost the same. You onle need to use 10 stars, and update the CSS to display each star as a half star. No logical updates …

  • http://twitter.com/franksvalli David Calhoun

    Unfortunately I think moving the actual inputs offscreen is causing it not to work on iOS.  I believe anything positioned offscreen is turned into text, and the user is unable to interact with it (cf. John Foliot), so this might be what’s causing the issue.

  • http://agrozoo.net/jsp/Galery.jsp Cvenkel Miran

    As per troubles with other things I have, I do have defaults_off. css which sets font-size to 0 for all elements. So in case that nothing appears you have to set fieldset,legend font size.

  • Glennytwoshoes

    Love the work you’ve done. I did notice a little odd behavior in FireFox. When you click on the stars, the page scrolls all the way to the top. It’s as though you are clicking on an ata with href=’#’.

    Any ideas on how to prevent this?

    • hrnsky

      i found that if you delete top:-9999px; line from .rating:not(:checked) > input assignment, it doesn’t scroll to top.

      • http://lea.verou.me/ Lea Verou

        Ah right, it should be hidden some other way then. Probably with clip: rect(0,0,0,0) or something.

        • hrnsky

          which lines are reset the stars ? if i click on 3 and want to change to 2 it doesn’t clear star 3 ? i think top:-9999; reset this but it doesn’t work either.

        • http://lea.verou.me/ Lea Verou

          Not sure what you mean, it works fine for me. Although I just noticed its appearance is pretty effed up in Firefox. Wasn’t like that before :(

        • hrnsky

          i created a form for submitting review. i for ex: i click on third star to give 3 stars for rate, it works but i want to change it with second star before submiting, it doesn’t clear third star.

          i’m testing on opera 12 and chrome 22, it works on jsfiddle perfectly too with these browsers. i’m using html5 doctype, is there anything wrong with that ?

        • http://lea.verou.me/ Lea Verou

          No, nothing is wrong with that. If it works in the fiddle, it’s logical that you didn’t copy something correctly…

        • hrnsky

          i hope so, thanks for this example.

  • http://twitter.com/jitendravyas Jitendra Vyas

    It’s nice with clean HTML. and degrade gracefully in IE9 too (no inner shadow) but that is fine. But is there any possibility to make half selection of arrow like this http://i.imgur.com/Jg3kS.jpg

    • http://leaverou.me Lea Verou

      Yes, if you use images and modify the CSS a bit. But I don’t have time to make a demo about that myself.

  • http://usb3gvn.com/ USB 3G

    Oh thanks, i appriciate that!

  • Pingback: Star Ratings With Very Little CSS | Transition Timing

  • Pingback: Star Ratings With Very Little CSS | Froey.us

  • Pingback: Star Ratings With Very Little CSS

  • Pingback: Star Ratings With Very Little CSS « JoinOG

  • Gumby

    Hi Lea
    I love what you have done here. Being a total novice, this is by far the simplest method I can find for adding rating stars to my website, and for that I am eternally grateful. However I just have one quick question:
    As you are aware, it doesn’t work on mobile safari. I was wondering if anybody could tell me how I can get the iphone/ipad to revert to the radio buttons. Is there some way of checking the browser in CSS.
    I really appreciate and help or pointers anyone could offer.
    Thanks in advance.

  • eamador

    EXACTLY WHAT I WAS LOOKING FOR!!!! THANKS A LOT!!!

  • http://www.facebook.com/shakir33 Shakir Hussain

    Nice work…. interesting…. simple…. awesome ….

  • Pingback: Powerful New CSS- and JavaScript Techniques | t1u

  • Pingback: Powerful New CSS- and JavaScript Techniques@smashing | seo博客大全

  • Pingback: Powerful New CSS- and JavaScript Techniques | Buypappa blog

  • Pingback: Powerful New CSS- and JavaScript Techniques | MyOfflineTheme.com Skyrocket Your Offline Business Just Now

  • Pingback: Powerful New CSS- and JavaScript Techniques | Web Design Kingston

  • Pingback: Powerful New CSS- and JavaScript Techniques | DigitalMofo

  • Pingback: Steve deGuzmanPowerful New CSS- and JavaScript Techniques » Steve deGuzman

  • Pingback: Powerful New CSS- and JavaScript Techniques « Web Development Website

  • Pingback: Powerful New CSSand JavaScript Techniques - rehavaPress

  • Pingback: Rutweb Technology : Powerful New CSS- and JavaScript Techniques

  • Pingback: Powerful New CSS- and JavaScript Techniques | TuTsRUS - All Adobe Tutorials - Photoshop | Illustrator | Encore | Premeire | After Effects

  • Pingback: Powerful New CSS- and JavaScript Techniques — Заметки по дизайну

  • Pingback: Powerful New CSS- and JavaScript-Techniques (2012 Edition) | Smashing Coding

  • Pingback: Powerful New CSS- and JavaScript Techniques | Sedation Dentist Wayne

  • Anonymous

    I seem to be having trouble using more than one of these on a single page. No matter what star field I select it only updates the first one. I thought maybe this had to do with using the same name for all the radio buttons so I made each one unique but that did not fix the problem. Any ideas?

    FIXED – The problem was I was using the same 5 “for” and “id” attributes for each star field. Changing just the “name” attribute wasn’t enough. I wrote a short PHP script to automate this process using a name variable when printing the star fields.

    • Kawsar

      thanks :)

    • Barry

      @jparis94:disqus do you might sharing your function? i stumbled upon the same issue. I made the name random but that didn’t fix it

      • jparis94

        Holy crap. I completely had forgotten about this comment (being from two years ago) then was really confused when I got an email about your comment yesterday and just ignored it. Coincidentally I ended at this same site again today for work and saw my username in the recent comments (from your mention). What are the chances lol

        I’ve since forgotten my disqus account so I’m just replying as guest but I swear it’s me! lol

        • Barry

          hahaha, tx jparis94 for your comment i recoginize your story sometimes i even stumble upon on my own question apparently i don’t store the answer ;).
          Anyway back on topic i did find a solution i edit my answer and just a unique name did the job.

          Wish you a good day!

  • Pingback: Powerful New CSS – and JavaScript Techniques

  • Pingback: Pure CSS star rating widget focusing on top when click on Firefox - feed99

  • Pingback: Powerful New CSS- and JavaScript Techniques

  • Pingback: » CSS TRANSAZIONI E ANIMAZIONI - PYG studio

  • http://www.facebook.com/goofydawg Brendan Delumpa

    Love this implementation! BTW, I created a Backbone.js widget using your CSS. http://jsfiddle.net/GoofyDawg/9VL7M/

  • Pingback: Bergstrom Productions Powerful New CSS- and JavaScript Techniques | Bergstrom Productions

  • Pingback: Button Switches with Checkboxes and CSS3 Fanciness | Developer Junk

  • KJ

    thanks

  • Pingback: 用单选按钮和 CSS3 技巧制作按键式开关 | 5迷3道 | HTML5和CSS3的真材实料

  • Pingback: 10 Awesome jQuery Rating Plugins | Websanova

  • Pingback: Powerful New CSS- and JavaScript Techniques « OhMyDev

  • Jens Törnell

    Very nice to solve this without JS.

  • Kawsar

    Nice solution. But can not repeat in one page. when repeat, found first rating is working only. i also add jquery to make the radio selected.

    $(‘.rating input[type="radio"]‘).click(function(){
    $(‘.rating input[type="radio"]‘).removeAttr(‘checked’);
    $(this).attr(‘checked’, ‘checked’);
    });

    if someone tell me how to repeat this feature? thanks in advance. :)

    • Emman Calabroso

      Yes. Encountered a similar problem with this code.

    • conor

      Change the “id” and “for” values. eg for one review have the numbers star1-star5. for the next review have the numbers star6-star10 etc

  • Jonathan Ogilvie

    Extending on your ideas and the ideas here (http://nerds.airbnb.com/quick-tip-making-star-ratings-with-one-image), here’s one that supports half-stars using images: http://jsfiddle.net/LTQrZ/18/

    • Emman Calabroso

      Cannot repeat in one page.

  • http://ajwebdesigner.in Ajinkya

    this is just amazing, i never knew CSS3 can do this :P btw Im having problem, after rating CSS whatever I add it doesnt work.

    • http://lea.verou.me/ Lea Verou

      Not sure what you mean by “whatever I add it doesnt [sic] work”… Please elaborate?

      • http://ajwebdesigner.in Ajinkya

        in my css page, after adding all ur CSS, if I try to add my any page css it doesnt work. for e.g. if i dont close one of the properties with semicoln the next properties wont work. something like that happening whn I add ur CSS. But if I add ur css at bottom of my css page everything works

        • Paul

          have you missed off the } from the end when you copied and pasted the code??

  • Guest

    When it degrates to a series of radio buttons, they are vertically stacked, with the radio button above the label text. Is there a way to make them stack horizontally instead?

    • samuelterrazas

      You could look into floating them first to see if that resolves your issue

  • kvl

    add/change in css

    .rating:not(:checked) > label::before {

    content: “2605″;

    }

  • dan

    Hi! There’s a way to disable clicks and assign a rate manually?

  • mongy910

    I LOVE THIS SO MUCH THANK YOU!!!!

  • svovaf

    Excellent post Lea! Love the CSS approach. Unfortunately CSS is not enough when you’ll need to save the votes and show average rate. Backend is necessary in such scenario.

    It happens to be that I’m the developer of the Rating-Widget project (http://rating-widget.com), which is a very user-friendly and full solution for a Rating System (client+backend). We also have WordPress Plugin (http://rating-widget.com/get-the-word-press-plugin/), Blogger Gadget (http://rating-widget.com/blog/star-rating-for-blogger/), Shopify App (http://apps.shopify.com/ratingwidget), and basic JavaScript+Html Code (http://rating-widget.com).

    Keep up with the awesome posts!

    • http://lea.verou.me/ Lea Verou

      Backend and extra code can be complementary, it doesn’t mean the entire technique is invalid because you need to add a little code to send the values to the server.

      • svovaf

        I’ve never said so – you are totally right!

      • Billy

        “Excellent post Lea! Love the CSS approach.”

    • Robert Pottorff

      /shameless self promotion

  • Peter Demaria

    Had some page jump in Firefox and IE when you clicked a radio button and the rating fieldset was a little ways down the page (jumped to the top, trying to follow the inputs or something).. changed this bit from top: -9999px to:

    .new-rating:not(:checked) > input {
    position: absolute;
    top: 100%;
    clip: rect(0,0,0,0);
    }

    Seems fine now.. still need to browser test some. Thanks for being such a CSS ninja (and sharing)!

    • Yiidir

      Try This :

      :v

    • Kate Sylvia

      Actually – there’s a better accessibile text css set ….

      .rating:not(:checked) > input {
      clip: rect(0px, 0px, 0px, 0px);
      height: 1px;
      margin: -1px;
      overflow: hidden;
      padding: 0;
      position: absolute;
      width: 1px;
      }

      solves everything including on complex page layouts because it handles things in place :)

      • Mark

        Awesome correction Kate! Much love! :D

  • michael

    how to make it respond with 1 to 5 stars based on database record field entry? I have submitted the value from the form as an integer into mysql record. How to retrieve that value and display it in a way that makes sense using 1 to 5 stars?

  • Pingback: Tıklanmaları Javascript yerine CSS ile işlemlemek

  • http://www.facebook.com/raisinghjio Rai Singh

    Thanks!

  • Pingback: Powerful New CSS- and JavaScript-Techniques (2012 Edition)

  • Mo

    mine didnt work the icons we wierd symbols im new to this how can i fix it ??

  • Andreas Baier

    Fixed jumping problem:

    .rating:not(:checked) > input {
    visibility:hidden;
    position: relative;
    top: 100%;
    clip: rect(0,0,0,0);
    }

    Top Idea Big Thank
    http://www.rechtsanwalt.net

  • Hossein

    Is this supposed to show overall rate? I don’t think so.

  • http://www.locodiego.info/ Diego Lerma

    Gracias! Thanks nice code! :-)

  • Imran Afzal

    I have created a Rating Widget Check my Website http://star-rating-widget.com/

  • bat

    There’s a considerable difference viewing in firefox vs chrome… chrome renders big stars and firefox little ones.

  • SangDeok Captain Cho

    I have a question..
    I want to locate this star rating in center
    How can I take care of it??

  • rbultitude

    Great solution this and I love the fact you always think about accessibility.

    One small suggestion: Use ‘left’ rather than ‘top’ to hide the not checked inputs else the page scrolls to the top when a label is clicked:

    .rating:not(:checked) > input {
    position:absolute;
    left:-9999px;
    clip:rect(0,0,0,0);
    }

  • Nicolò Martini

    I use another technique to syle up radio-based stars without js nor dom order inversion and with much much less css: http://jsfiddle.net/nicmart/gRwsy/

    • Aaron

      This solution necessitates a rating, however. If a rating isn’t supplied and no radio is checked, all the stars are filled, as though giving the highest rating.

    • http://torkiljohnsen.com Torkil Johnsen

      Looks good at first glance. Solving this without dom order reversion is definitely better, as that leaves the door open for sensible keyboard navigation when trying to make this element accessible.

  • Pingback: BUTTON SWITCHES WITH CHECKBOXES AND CSS3 FANCINESS

  • Trey Rulon

    Thank you to the passengers, carers and staff that
    attended the Ozmates Christmas Passenger Party – IT WAS FANTASTIC!!!!!! We hope
    that you all enjoyed yourselves and watch this space for some brilliant party
    pics!
    For more info visit: Accessable Vehicles

  • Guest User

    What’s the quickest way to “turn off” the ratings? I must admit that the CSS used here is beyond my rudimentary CSS knowledge.

  • http://panduantemplateblog.com Ana Sriwahyuni

    just sample and not working for click to do, not for all

  • Piratehouse
  • Pingback: Using Font Awesome in an Accessible, Bindable Star Rating Control | They Call Me Mister James