<h1>Pure CSS Star Rating System!!</h1>
<p>Using a sort of <strong>"previous sibling"</strong> selector</p>
<div class="rating">
  <!--elements are in reversed order, to allow "previous sibling selectors" in CSS-->
  <input aria-flowto="rating0" class="rating__input" type="radio" name="rating" value="5" id="rating5">
  <label class="rating__label" for="rating5">☆
    <span class="rating__star">5 Stars</span> 
  <input aria-flowto="rating5"  class="rating__input" type="radio" name="rating" value="4" id="rating4">
  <label class="rating__label" for="rating4">☆
    <span class="rating__star">4 Stars</span> 
  <input aria-flowto="rating4" class="rating__input" type="radio" name="rating" value="3" id="rating3">
  <label class="rating__label" for="rating3">☆
    <span class="rating__star">3 Stars</span> 
  <input aria-flowto="rating3" class="rating__input" type="radio" name="rating" value="2" id="rating2">
  <label class="rating__label" for="rating2">☆
    <span class="rating__star">2 Stars</span> 
  <input aria-flowto="rating2" class="rating__input" type="radio" name="rating" value="1" id="rating1" aria-flowto="rating2">
  <label class="rating__label" for="rating1">☆
    <span class="rating__star">1 Stars</span> 
  <input aria-flowto="rating1" class="rating__input" type="radio" name="rating" value="0" id="rating0">
  <label class="rating__label rating__label--hidden" for="rating0">
    <span class="rating__star">Not rated yet </span>
/*shows the stars side by side, centered, and in reverse order than the HMTL*/
.rating {
  display: flex;
  flex-direction: row-reverse;
  justify-content: center;
  border: 3px dashed #333;
  padding: 1em;

/*hides the radio buttons by forcing them out of the viewport*/
  position: absolute; 
  left: -100vw;
/*hides label for 0 (unset)star rating */

/* hides spans from sighted users */
  position: absolute; left: -100vw;
  font-size: 1px

.rating:active {
  border-color: yellow;

/*style the empty stars, sets position:relative as base for pseudo-elements*/
.rating__label {
  position: relative;
  width: 1.1em;
  font-size: 15vw;
  color: #FFD700;
  cursor: pointer;

/* sets filled star pseudo-elements */
  content: "\2605";
  position: absolute;
  opacity: 0;

/*overlays a filled start character to the hovered element and all previous siblings*/
.rating__label:hover ~ .rating__label:before {
  opacity: 1 !important;

/*overlays a filled start character on the selected element and all previous siblings*/
.rating__input:checked ~ .rating__label:before{

/*when an element is selected and pointer re-enters the rating container, selected rate and siblings get semi transparent, as reminder of current selection*/
.rating:hover > .rating__input:checked ~ .rating__label:before{ opacity: 0.4; }

/*just aesthetics*/
body{ background: #222225; color: white;}
h1, p{ text-align: center;}
p{ font-size: 1.2rem;}
@media only screen and (max-width: 600px) {
  h1{font-size: 14px;}
  p{font-size: 12px;}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.