feedback, star rating, user rating-2800867.jpg

Pure CSS only HTML Star Rating (No Javascript)

This is THE most compact and optimized version of a pure CSS only HTML star rating. It covers a form input field as well as an output only score element.

I was searching a long time for a good CSS only solution for a star input field for my Grav Ratings plugin. I found a few ones (list a the end of this post), but they could still be optimized a lot or contained a few bugs. I’ve managed to sort them all out and give you the best version of a pure CSS star rating element.

Prerequisites

In order to get started I wanted to note, that the following code is based on Font Awesome 4, but also works with Font Awesome 5, Line Awesome 1.3 and even pure Unicode stars as well. You can also easily adapt other icon fonts as well.

Instead of writing pure CSS I have used the very common SCSS. It should be easy for you to convert it to CSS, if that is what you need instead.

Example

So here is a ready to use example which shows what we will be building in this posts. It contains a fixed star rating first, which can be used to show the user a rating summary and a form input field to let the user select the appropriate star rating.

The output fields work for half steps (0.5) as well, the input only accepts full stars. It can be easily tweaked to allow more than 5 stars, but I’ve chosen 5 here, as it is most common.

Step 1: Star Icon Definition

Before we start, we must declare how a star should look like. Since we are using Font Awesome 4 in this example, we need to lookup the font numbers of the corresponding star icons. Those definitions are used in the following steps again.

// Star definitions
%base-star {
  display: inline-block; 
  
  &:after {
    font-family: "FontAwesome";
    font-size: 1.5em;
    color: #FFC600;
  }
};

%full-star {
  @extend %base-star;
  
  &:after {
    content: "\f005";    
  }
};

%half-star {
  @extend %base-star;
  
  &:after {    
    content: "\f123";
  }
};

%empty-star {
  @extend %base-star;
  
  &:after {
    content: "\f006";
  }
};
Code language: SCSS (scss)

And as promised a version for the Font Awesome 5 or Line Awesome users:

// Star definitions
%base-star {
  display: inline-block; 
  
  &:after {
    font-family: "Font Awesome 5 Pro", "Line Awesome Free";
    font-size: 1.5em;
    color: #FFC600;
  }
};

%full-star {
  @extend %base-star;
  
  &:after {
    font-weight: 900;
    content: "\f005";
  }
};

%half-star {
  @extend %base-star;
  
  &:after {    
    font-weight: 900;
    content: "\f5c0";
  }
};

%empty-star {
  @extend %base-star;
  
  &:after {
    font-weight: 400;
    content: "\f005";
  }
};
Code language: SCSS (scss)

And even a pure HTML Unicode solution without any icon font at all!

// Star definitions
%base-star {
  display: inline-block; 
  
  &:after, &:before {
    font-size: 2em;
    color: #FFC600;
  }
};

%full-star {
  @extend %base-star;
  
  &:after {
    content: "\2605";
  }
};

%half-star {
  @extend %base-star;
  
  &:before {
    position: absolute;
    content: "\2606"; 
  }
  &:after {
    position: absolute;
    content: "\2605"; 
    background: linear-gradient(to right, #FFC600 50%,transparent 50%);
    background-clip: text;
    // Experimental: https://caniuse.com/mdn-css_properties_-webkit-text-fill-color
    -webkit-text-fill-color: transparent;
  }
};

%empty-star {
  @extend %base-star;
  
  &:after {
    content: "\2606";
  }
};
Code language: SCSS (scss)

Step 2: Star Rating Score Element

The following simple CSS and HTML is used to output a CSS only star rating score element.

// 5 Star Rating Score
.rating-score {
  display: inline-flex;
  flex-direction: row;
  align-items: flex-start;
  margin: 0;
  padding: 0;

  .rating-score-item {
    @extend %empty-star;
  }

  @for $i from 1 through 5 {
    &[data-rating='#{$i}'] {
      .rating-score-item:nth-child(-n + #{$i}) {
        @extend %full-star;
      }
    }
  }
  
  @for $i from 0 through 4 {
    &[data-rating='#{$i + 0.5}'] {
      .rating-score-item:nth-child(-n + #{$i}) {
        @extend %full-star;
      }

      .rating-score-item:nth-child(#{$i + 1}) {
        @extend %half-star;
      }
    }
  }
}
Code language: SCSS (scss)

Note the data-rating attribute in the outer list element. It can be used to set the target rating score. You can also use half steps (e.g. 3.5) here.

<ul class="rating-score" data-rating="4.5">
  <li class="rating-score-item"></li>
  <li class="rating-score-item"></li>
  <li class="rating-score-item"></li>
  <li class="rating-score-item"></li>
  <li class="rating-score-item"></li>
</ul>
Code language: HTML, XML (xml)

Step 3: Star Rating Form Input Field

Next we are creating the star rating form input field. It can be used in any form and will work like any other radio button. The CSS is quite tricky, as we need to make sure to overwrite the colors at a specific CSS selector level. Once I got there, it is pretty straight forward:

// 5 Star Rating Form Field
.rating-input {
  border: none;
  display: inline-flex;
  flex-direction: row-reverse;
  justify-content: flex-end;
  margin: 0;
  padding: 0;

  > input {
    display: none;
  }

  > label {
    @extend %empty-star;
  }

  // Selected star color
  > input:checked ~ label {
    @extend %full-star;
  }

  // On hover color all stars grey by default
  &:hover > input + label {
    @extend %empty-star;
  }

  // Hover star color
  &:hover > input + label:hover,
  &:hover > input + label:hover ~ input + label {
    @extend %full-star;
  }
}
Code language: SCSS (scss)

And finally the minimum HTML, also quite simple:

<fieldset class="rating-input">
  <input type="radio" value="5" id="stars-star5" name="rating">
  <label for="stars-star5" title="5 Stars"></label>
  <input type="radio" value="4" id="stars-star4" name="rating">
  <label for="stars-star4" title="4 Stars"></label>
  <input type="radio" value="3" id="stars-star3" name="rating">
  <label for="stars-star3" title="3 Stars"></label>
  <input type="radio" value="2" id="stars-star2" name="rating">
  <label for="stars-star2" title="2 Stars"></label>
  <input type="radio" value="1" id="stars-star1" name="rating">
  <label for="stars-star1" title="1 Stars"></label>
</fieldset>
Code language: HTML, XML (xml)

Continue Reading

Now this looks quite simple, but it took me a lot of time to come to that final version. It is the most compact, best looking and clear CSS only star rating HTML element that I’ve found. In the links below you can find other codepens on which this solution is based on, but as an improved version.

Did you find anything yet to improve more? Let me know in the comments!

Buy Me A Coffee

Leave a Comment

Your email address will not be published. Required fields are marked *