I'm trying to make a 5 circle rating system using CSS and HTML only (see below image for what I'd like it to look like), but I'm not sure how to achieve this.
My initial idea was to make 5 circles and then somehow use them as a mask for a background colour that's the complete width of all 5 circles. So the first image has a width of 90% with a background colour of #4a494a
, while the second image has a width of 60% and again, a background colour of #4a494a
.
These circles are fixed so no interaction shall be needed to paint them.
Does anyone have any ideas on how I might do this?
You can do this by using a pseudo-element (.rating:after
) that is positioned on top of div.rating
. The .rating
has a linear-gradient
whose background-size
determines how much of the circle is filled and in .rating:after
there is a radial-gradient
which produces five circles that act like the masks).
I have used an animation to show how the circle gets filled as background-size
increases. You can set the required background-size
using JS (or any backend code that generates the rating element) and then add it via inline styles to the div.rating
.
Using this approach, even in between ratings (or ratings of any value like 3.65, 2.25, 1.85 etc) can be handled with ease by just calculating the required background-size
. I have added a few samples in the demo.
.rating {
position: relative;
height: 50px;
width: 250px;
background: linear-gradient(to right, black, black);
background-repeat: no-repeat;
background-position: 0px 0px;
background-size: 0px 100%;
}
.rating.auto-anim {
animation: fill-circle 5s ease infinite;
}
.rating:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
background: radial-gradient(20px at center, transparent 7.5px, beige 9px);
background-position: 0px 0px;
background-size: 50px 100%;
border: 1px solid;
}
@keyframes fill-circle {
to {
background-size: 100% 100%;
}
}
<div class='rating auto-anim'></div>
<div class='rating' style="background-size: 50px 100%;"></div> <!-- rating of 1 -->
<div class='rating' style="background-size: 75px 100%;"></div> <!-- rating of 1.5 -->
<div class='rating' style="background-size: 121.25px 100%;"></div> <!-- rating of 2.25 -->
<div class='rating' style="background-size: 228.75px 100%;"></div> <!-- rating of 4.75 -->
<div class='rating' style="background-size: 177.25px 100%;"></div> <!-- rating of 3.65 -->
<div class='rating' style="background-size: 80.25px 100%;"></div> <!-- rating of 1.85 -->
<!--
Background Size Calculation Logic: Each circle is only 15px wide with 17.5px gap on either side
1 rating = 50px (for 1 circle)
1.5 rating = 50px (for 1 circle) + 17.5px (gap before 2nd circle on left) + 7.5px (.5 of 15px circle)
2.25 rating = 100px (for 2 circles) + 17.5px (gap before 3rd circle on left) + 3.75px (.25 of 15px circle)
4.75 rating = 200px (for 4 circles) + 17.5px (gap before 5th circle on left) + 11.25px (.75 of 20px circle)
3.65 rating = 150px (for 3 circles) + 17.5px (gap before 4th circle on left) + 9.75px (.65 of 20px circle)
1.85 rating = 50px (for 1 circle) + 17.5px (gap before 2nd circle on left) + 12.75px (.85 of 20px circle)
-->