Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a fixed 5 circle rating using CSS/HTML

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.

Circle Rating

rating 2

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?

like image 996
Mo Martin Avatar asked Mar 20 '16 16:03

Mo Martin


People also ask

How do you give a rating in HTML?

You can set rated value with attribute data-value="..." . Value for this attribute must be a valid number value and less or equal of count of stars. If your value is a float, you can use special attribute data-round-func="round|ceil|floor" to set round function.

How do I create a rounded circle in CSS?

To create a circle we can set the border-radius on the element. This will create curved corners on the element. If we set it to 50% it will create a circle. If you set a different width and height we will get an oval instead.

How do you write the code for a circle in HTML?

There is not technically a way to draw a circle with HTML (there isn't a <circle> HTML tag), but a circle can be drawn. Show activity on this post. You can use border-radius property, or make a div with fixed height and width and a background with png circle.


3 Answers

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)
-->
like image 171
Harry Avatar answered Sep 19 '22 04:09

Harry


This can be completed with quite a small and easy amount of CSS to be able to create the effect you need.

.rating {
  direction: rtl;
  text-align: center;
}
.rating > span {
  display: inline-block;
  position: relative;
  box-sizing: border-box;
  width: 20px;
  height: 20px;
  border: 1px solid black;
  border-radius: 10px;
}
.rating > span:hover,
.rating > span:hover ~ span {
  background: transparent;
}
.rating > span:hover:before,
.rating > span:hover ~ span:before {
  content: "";
  position: absolute;
  left: -2px;
  top: -2px;
  background: gold;
  width: 20px;
  height: 20px;
  border: 1px solid gold;
  border-radius: 20px;
}
<div class="rating">
  <span></span><span></span><span></span><span></span><span></span>
</div>

This is a variant of Star Ratings developed by css-tricks.com. Click here to read more!

like image 27
Stewartside Avatar answered Sep 20 '22 04:09

Stewartside


If you use some clever css along with some radio inputs you can achieve this with pure css and html, while even keeping it interactive. Have a look at the fiddle I set up: https://jsfiddle.net/2rs79wsh/

#ratings {
  font-size: 0;
}
#ratings * {
  float: right;
}
#ratings input {
  display: none;
}
#ratings label {
  width: 20px;
  height: 40px;
  background-color: #ccc;
  display: inline-block;
}
#ratings label:nth-of-type(even) {
  border-top-left-radius: 20px;
  border-bottom-left-radius: 20px;
  margin-left: 10px;
}
#ratings label:nth-of-type(odd) {
  border-top-right-radius: 20px;
  border-bottom-right-radius: 20px;
  margin-right: 10px;
}
#ratings input:checked ~ label {
  background-color: red;
}
<div id="ratings">
  <input type="radio" id="rating-10" name="rating" value="10">
  <label for="rating-10"></label>
  ...
  <input type="radio" id="rating-1" name="rating" value="1" checked=checked>
  <label for="rating-1"></label>
</div>

The circles you see are the labels for the inputs. The order is reversed (by using float right), so you can use ~ selector to show the state of all the siblings coming after the checked one. The radio's are there to store the state and should even allow you to send any changes back by submitting this inside a form. Each circle consists of two labels, so depending on which halve of the circle you click you'll get a different score. The odd/even selectors moves the two halves together two make it look like a single circle.

Feel free to ask if anything is unclear!

like image 25
Pevara Avatar answered Sep 19 '22 04:09

Pevara