2

I want to make a star rating by hiding the input (radio buttons) and just displaying the label (which is star shaped). By clicking on one of the stars, all stars before it should become yellow too. So I wrote the following:

HTML and CSS creating radio buttons and labels:

input:not(:checked)~label:hover,
label:hover~input:not(checked)~label {
  color: #fd4;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<input type="radio" name="rate" id="rate-1">
<label for="rate-1" class="fa-solid fa-star"></label>
<input type="radio" name="rate" id="rate-2">
<label for="rate-2" class="fa-solid fa-star"></label>
<input type="radio" name="rate" id="rate-3">
<label for="rate-3" class="fa-solid fa-star"></label>
<input type="radio" name="rate" id="rate-4">
<label for="rate-4" class="fa-solid fa-star"></label>
<input type="radio" name="rate" id="rate-5">
<label for="rate-5" class="fa-solid fa-star"></label>

But the stars are highlighted from right to left, so if you for example hover over 4 stars, the forth and fifth star is highlighted.

picture of example

How can I fix this?

m4n0
  • 29,823
  • 27
  • 76
  • 89

2 Answers2

2

A simple solution would be to add a container with display:flex; and use flex-direction to reverse the elements. Because the elements are displayed in the DOM reversed, you will need to be sure to reverse the order of the elements in the HTML as well, so that you are still getting the correct rating.

input:not(:checked)~label:hover,
label:hover~input:not(checked)~label {
  color: #fd4;
}
.rating-container {
  display:flex;
  flex-direction:row-reverse;
  justify-content:center;
}
input[type="radio"] {
  display:none;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div class="rating-container">
  <input type="radio" name="rate" id="rate-5">
  <label for="rate-5" class="fa-solid fa-star"></label>
  <input type="radio" name="rate" id="rate-4">
  <label for="rate-4" class="fa-solid fa-star"></label>
  <input type="radio" name="rate" id="rate-3">
  <label for="rate-3" class="fa-solid fa-star"></label>
  <input type="radio" name="rate" id="rate-2">
  <label for="rate-2" class="fa-solid fa-star"></label>
  <input type="radio" name="rate" id="rate-1">
  <label for="rate-1" class="fa-solid fa-star"></label>
</div>
user19103974
  • 300
  • 2
  • 9
0

Alternative solution is placing it in div, giving it flex so there's no space between labels, and whenever you hover over div radio buttons will become gold but those that precede the directly hovered radio button will be given a normal color.

.container {
  display: flex;
}

div:hover > label {
  color: #fd4;
}

div:hover > label:hover ~ label {
  color: #000;
}

input[type=radio] {
    display: none;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div class="container"> 
  <input type="radio" name="rate" id="rate-1">
  <label for="rate-1" class="fa-solid fa-star"></label>
  <input type="radio" name="rate" id="rate-2">
  <label for="rate-2" class="fa-solid fa-star"></label>
  <input type="radio" name="rate" id="rate-3">
  <label for="rate-3" class="fa-solid fa-star"></label>
  <input type="radio" name="rate" id="rate-4">
  <label for="rate-4" class="fa-solid fa-star"></label>
  <input type="radio" name="rate" id="rate-5">
  <label for="rate-5" class="fa-solid fa-star"></label>
</div>

I have to note that while it works quite well for hovering, I can't find a way without JS to make the stars stay golden after checking, it's far easier to implement in accepted solution.

DGX37
  • 304
  • 3
  • 12