Skip to content

Instantly share code, notes, and snippets.

@prof3ssorSt3v3
Created March 12, 2018 18:09
Show Gist options
  • Save prof3ssorSt3v3/29e623d441e8174ffaef17741a1bba14 to your computer and use it in GitHub Desktop.
Save prof3ssorSt3v3/29e623d441e8174ffaef17741a1bba14 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Star Rating System</title>
<meta name="viewport" content="width=device-width">
<style>
.star{
color: goldenrod;
font-size: 2.0rem;
padding: 0 1rem; /* space out the stars */
}
.star::before{
content: '\2606'; /* star outline */
cursor: pointer;
}
.star.rated::before{
/* the style for a selected star */
content: '\2605'; /* filled star */
}
.stars{
counter-reset: rateme 0;
font-size: 2.0rem;
font-weight: 900;
}
.star.rated{
counter-increment: rateme 1;
}
.stars::after{
content: counter(rateme) '/5';
}
</style>
</head>
<body>
<!-- alternate codepen version https://codepen.io/mad-d/pen/aJMPWr?editors=0010 -->
<h1>Star Rating System</h1>
<div class="stars" data-rating="3">
<span class="star">&nbsp;</span>
<span class="star">&nbsp;</span>
<span class="star">&nbsp;</span>
<span class="star">&nbsp;</span>
<span class="star">&nbsp;</span>
</div>
<p>The number shown after the CSS is generated with a CSS counter.</p>
<script>
//initial setup
document.addEventListener('DOMContentLoaded', function(){
let stars = document.querySelectorAll('.star');
stars.forEach(function(star){
star.addEventListener('click', setRating);
});
let rating = parseInt(document.querySelector('.stars').getAttribute('data-rating'));
let target = stars[rating - 1];
target.dispatchEvent(new MouseEvent('click'));
});
function setRating(ev){
let span = ev.currentTarget;
let stars = document.querySelectorAll('.star');
let match = false;
let num = 0;
stars.forEach(function(star, index){
if(match){
star.classList.remove('rated');
}else{
star.classList.add('rated');
}
//are we currently looking at the span that was clicked
if(star === span){
match = true;
num = index + 1;
}
});
document.querySelector('.stars').setAttribute('data-rating', num);
}
</script>
</body>
</html>
@jpvajda
Copy link

jpvajda commented Oct 9, 2018

Thanks for sharing! I used the Code Pen for reference!

@dh-github
Copy link

Nice script!

Ran into an error when running on chrome:

Uncaught TypeError: Cannot read property 'dispatchEvent' of undefined
at HTMLDocument. (stars.html:55)
(anonymous) @ stars.html:55

That corresponds to :
target.dispatchEvent(new MouseEvent('click'));

Looks like there is a similar error in ng-fullcalendar

fullcalendar/fullcalendar-angular#24

...just fyi

@dh-github
Copy link

Ah, my bad. I produced the error by setting data-rating="0" at the outset.

@madsbad
Copy link

madsbad commented Apr 2, 2019

This is awesome. I'm trying to figure out how to make a rating system but make the chosen rating become a post. Then have the ratings compile to make a summary of ratings. This is a helpful first step, thank you

@rameezl
Copy link

rameezl commented Aug 2, 2019

Thank you so much for this code works great! Im currently making a survey and was able to use this rating system for 1 question, but now im trying to do another question with a rating system but when i copy and paste the code, both ratings are linked together, anyways to make them work separately? Sorry, new to this.

@prof3ssorSt3v3
Copy link
Author

Thank you so much for this code works great! Im currently making a survey and was able to use this rating system for 1 question, but now im trying to do another question with a rating system but when i copy and paste the code, both ratings are linked together, anyways to make them work separately? Sorry, new to this.

You just need to have something unique in the HTML that identifies each group. A different CSS classname works or combine two classnames.

<div class="stars one"> </div>
<div class="stars two"> </div>

They are all "stars" groups but the "one" and "two" make the group unique.

@rory81
Copy link

rory81 commented Jan 26, 2020

First of all, thank you for sharing this code, it works great! I am a newbie when it comes to jquery, but how do I make the star rating required for the user to fill in? I have tried to put it in a form and use , but that doesn't work.

Thanks again!

@prof3ssorSt3v3
Copy link
Author

First of all, thank you for sharing this code, it works great! I am a newbie when it comes to jquery, but how do I make the star rating required for the user to fill in? I have tried to put it in a form and use , but that doesn't work.

Thanks again!

I never use jQuery. There is no jQuery in my samples, just plain JavaScript.

If you want to make something like this required then you need to check that you have a value for which star the user clicked when they submit the form. You will have a function that runs when the form is submitted and you need to add your code to check for the value inside that function.

Just having it inside a form will not do anything because these are not form input elements.

@tobystic
Copy link

tobystic commented Apr 4, 2020

if you need to put the stars in the center of the page (margin center), you have to add it to the div tag above the star class. A div is a block element, and will apply across the width of the container unless a width is set. A span is an inline element, and will have the width of the text inside it, so applying this to the span in CSS sheet might not work

So line 38 above:

    <div class="stars" data-rating="3">
        <span class="star">&nbsp;</span>
        <span class="star">&nbsp;</span>
        <span class="star">&nbsp;</span>

will become

<div style="text-align: center; class="stars" data-rating="3">
        <span class="star">&nbsp;</span>
        <span class="star">&nbsp;</span>
        <span class="star">&nbsp;</span>

Hope that helps someone

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment