Currently I'm making a rating system for a webshop. Basically how I want it to work:
If visitor never rated before:
- Visitor hovers over a star
- The previous and current stars will be yellow, the next stars gray (done with class)
- If the visitor leaves the hover, reset all stars to the old state
- If the visitor clicks on a star, save it, calculate the next star values and update the array.
I'm using font awesome so I'm not using any images. The problem now is that if I hover over a star, it works, but if I want to move from star to star it glitches (because there's a little gap between the stars and it means it'll reset the stars first).
jsfiddle: /
JS:
var current_star_statusses = [];
star_elements = $('.fa-star');
star_elements.each(function(i, elem)
{
current_star_statusses.push($(elem).hasClass('yellow'));
});
star_elements.mouseenter(changeRatingStars);
star_elements.mouseleave(resetRatingStars);
/**
* Changes the rating star colors when hovering over it.
*/
function changeRatingStars()
{
// Current star hovered
var star = $(this);
// Removes all colors first from all stars
$('.fa-star').removeClass('gray').removeClass('yellow');
// Makes the current hovered star yellow
star.addClass('yellow');
// Makes the previous stars yellow and the next stars gray
star.parent().prevAll().children('.fa-star').addClass('yellow');
star.parent().nextAll().children('.fa-star').addClass('gray');
}
/**
* Resets the rating star colors when not hovered anymore.
*/
function resetRatingStars()
{
star_elements.each(function(i, elem)
{
$(elem).removeClass('yellow').removeClass('gray').addClass(current_star_statusses[i] ? 'yellow' : 'gray');
});
}
HTML:
<ul class="list-inline rating-list">
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star gray"></i></li>
</ul>
CSS:
.fa-star:before {
content: "\f005";
}
.rating-list li i.yellow {
color: #FFD700;
}
.rating-list li i.gray {
color: #bbb;
}
.list-inline>li {
display: inline-block;
padding-right: 5px;
padding-left: 5px;
}
.rating-list li {
padding: 0px;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transform: translate(0, 0);
}
I know there are a lot of libraries that makes it easier but I'd like to keep it my own code if I can.
Currently I'm making a rating system for a webshop. Basically how I want it to work:
If visitor never rated before:
- Visitor hovers over a star
- The previous and current stars will be yellow, the next stars gray (done with class)
- If the visitor leaves the hover, reset all stars to the old state
- If the visitor clicks on a star, save it, calculate the next star values and update the array.
I'm using font awesome so I'm not using any images. The problem now is that if I hover over a star, it works, but if I want to move from star to star it glitches (because there's a little gap between the stars and it means it'll reset the stars first).
jsfiddle: https://jsfiddle/uappvz3y/
JS:
var current_star_statusses = [];
star_elements = $('.fa-star');
star_elements.each(function(i, elem)
{
current_star_statusses.push($(elem).hasClass('yellow'));
});
star_elements.mouseenter(changeRatingStars);
star_elements.mouseleave(resetRatingStars);
/**
* Changes the rating star colors when hovering over it.
*/
function changeRatingStars()
{
// Current star hovered
var star = $(this);
// Removes all colors first from all stars
$('.fa-star').removeClass('gray').removeClass('yellow');
// Makes the current hovered star yellow
star.addClass('yellow');
// Makes the previous stars yellow and the next stars gray
star.parent().prevAll().children('.fa-star').addClass('yellow');
star.parent().nextAll().children('.fa-star').addClass('gray');
}
/**
* Resets the rating star colors when not hovered anymore.
*/
function resetRatingStars()
{
star_elements.each(function(i, elem)
{
$(elem).removeClass('yellow').removeClass('gray').addClass(current_star_statusses[i] ? 'yellow' : 'gray');
});
}
HTML:
<ul class="list-inline rating-list">
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star gray"></i></li>
</ul>
CSS:
.fa-star:before {
content: "\f005";
}
.rating-list li i.yellow {
color: #FFD700;
}
.rating-list li i.gray {
color: #bbb;
}
.list-inline>li {
display: inline-block;
padding-right: 5px;
padding-left: 5px;
}
.rating-list li {
padding: 0px;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transform: translate(0, 0);
}
I know there are a lot of libraries that makes it easier but I'd like to keep it my own code if I can.
Share Improve this question edited Feb 24, 2017 at 9:24 neophyte 6,6242 gold badges31 silver badges43 bronze badges asked Feb 24, 2017 at 8:52 Joshua BakkerJoshua Bakker 2,3683 gold badges36 silver badges66 bronze badges3 Answers
Reset to default 8You can make stars rating using pure CSS. Float stars to right, and apply hover effect for li
that has padding.
.rating-list li {
float: right;
color: #ddd;
padding: 10px 5px;
}
.rating-list li:hover,
.rating-list li:hover ~ li {
color: #ffd700;
}
.rating-list {
display: inline-block;
list-style: none;
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<ul class="list-inline rating-list">
<li><i class="fa fa-star" title="Rate 5"></i></li>
<li><i class="fa fa-star" title="Rate 4"></i></li>
<li><i class="fa fa-star" title="Rate 3"></i></li>
<li><i class="fa fa-star" title="Rate 2"></i></li>
<li><i class="fa fa-star" title="Rate 1"></i></li>
</ul>
I changed these 4 lines of code.
star_elements = $('.fa-star').parent();
star_elements.find(".fa-star").each(function(i, elem) {
current_star_statusses.push($(elem).hasClass('yellow'));
});
star_elements.find(".fa-star").mouseenter(changeRatingStars);
star_elements.find(".fa-star").mouseleave(resetRatingStars);
So now the star_element
is the li
.
Also if you pref jsfiddle, here is a link
var current_star_statusses = [];
star_elements = $('.fa-star').parent();
star_elements.find(".fa-star").each(function(i, elem) {
current_star_statusses.push($(elem).hasClass('yellow'));
});
star_elements.find(".fa-star").mouseenter(changeRatingStars);
star_elements.find(".fa-star").mouseleave(resetRatingStars);
/**
* Changes the rating star colors when hovering over it.
*/
function changeRatingStars() {
// Current star hovered
var star = $(this);
// Removes all colors first from all stars
$('.fa-star').removeClass('gray').removeClass('yellow');
// Makes the current hovered star yellow
star.addClass('yellow');
// Makes the previous stars yellow and the next stars gray
star.parent().prevAll().children('.fa-star').addClass('yellow');
star.parent().nextAll().children('.fa-star').addClass('gray');
}
/**
* Resets the rating star colors when not hovered anymore.
*/
function resetRatingStars() {
star_elements.each(function(i, elem) {
$(elem).removeClass('yellow').removeClass('gray').addClass(current_star_statusses[i] ? 'yellow' : 'gray');
});
}
.fa-star:before {
content: "\f005";
}
.rating-list li i.yellow {
color: #FFD700;
}
.rating-list li i.gray {
color: #bbb;
}
.list-inline>li {
display: inline-block;
padding-right: 5px;
padding-left: 5px;
}
.rating-list li {
padding: 0px;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transform: translate(0, 0);
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<ul class="list-inline rating-list">
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star gray"></i></li>
</ul>
There is a much simpler solution: use paddings on the .fa
elements instead, and use float: left
for the list items, which means that there will be no spacing between each star.
These few rules are sufficient to achieve the effect you intend to do:
.list-inline {
list-style: none;
padding: 0;
margin: 0;
overflow: hidden;
}
.list-inline > li {
float: left;
}
.rating-list li {
padding: 0px;
}
.rating-list li .fa {
padding-right: 5px;
}
Here is a proof-of-concept example, leaving your JS code unchanged:
$(function() {
var current_star_statusses = [];
star_elements = $('.fa-star');
star_elements.each(function(i, elem) {
current_star_statusses.push($(elem).hasClass('yellow'));
});
star_elements.mouseenter(changeRatingStars);
star_elements.mouseleave(resetRatingStars);
/**
* Changes the rating star colors when hovering over it.
*/
function changeRatingStars() {
// Current star hovered
var star = $(this);
// Removes all colors first from all stars
$('.fa-star').removeClass('gray').removeClass('yellow');
// Makes the current hovered star yellow
star.addClass('yellow');
// Makes the previous stars yellow and the next stars gray
star.parent().prevAll().children('.fa-star').addClass('yellow');
star.parent().nextAll().children('.fa-star').addClass('gray');
}
/**
* Resets the rating star colors when not hovered anymore.
*/
function resetRatingStars() {
star_elements.each(function(i, elem) {
$(elem).removeClass('yellow').removeClass('gray').addClass(current_star_statusses[i] ? 'yellow' : 'gray');
});
}
});
.fa-star:before {
content: "\f005";
}
.rating-list li i.yellow {
color: #FFD700;
}
.rating-list li i.gray {
color: #bbb;
}
.list-inline {
list-style: none;
padding: 0;
margin: 0;
overflow: hidden;
}
.list-inline>li {
float: left;
}
.rating-list li {
padding: 0px;
}
.rating-list li .fa {
padding-right: 5px;
}
.fa {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transform: translate(0, 0);
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="list-inline rating-list">
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star yellow"></i></li>
<li><i class="fa fa-star gray"></i></li>
</ul>