tomphilps
tomphilps

Reputation: 159

CSS for star ratings via FontAwesome

I've tried a few variations of CSS star ratings via different methods, and am trying to implement the following via FontAwesome rather than using a sprite. I want to be able to include half stars ideally, but this is where the example below is failing. This is what I've tried so far. I can't get the half / partial star to work correctly here. Any pointers greatly appreciated!

.score {
  display: block;
  font-size: 16px;
  position: relative;
  overflow: hidden;
}

.score-wrap {
  display: inline-block;
  position: relative;
  overflow: hidden;
  height: 19px;
}

.score .stars-active {
  color: #EEBD01;
  position: relative;
  z-index: 10;
  display: inline-block;
}

.score .stars-inactive {
  color: grey;
  position: absolute;
  top: 0;
  left: 0;
  -webkit-text-stroke: initial;
  overflow: hidden;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" />

<span class="score">
    <div class="score-wrap">
        <span class="stars-active" style="width:88%">
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
        </span>
<span class="stars-inactive">
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
        </span>
</div>
</span>

<span class="score">
    <div class="score-wrap">
        <span class="stars-active" style="width:50%">
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
        </span>
<span class="stars-inactive">
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
        </span>
</div>
</span>

<span class="score">
    <div class="score-wrap">
        <span class="stars-active" style="width:100%">
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
        </span>
<span class="stars-inactive">
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
        </span>
</div>
</span>

<span class="score">
    <div class="score-wrap">
        <span class="stars-active" style="width:0%">
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
        </span>
<span class="stars-inactive">
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
        </span>
</div>
</span>

Upvotes: 10

Views: 29908

Answers (7)

Roberto Murphy
Roberto Murphy

Reputation: 478

★★★⯪☆

Just use Unicode characters and then use https://www.babelstone.co.uk/Fonts/Shapes.html font as it has ⯪ (STAR WITH LEFT HALF BLACK)

★★★⯪☆

Given the characters (glyphs) above, lets say that ⯪ is rendered as ▯ or some other character that denotes that the glyph is missing from the font. The way you fix this is that you copy ⯪ (missing glyph) and then in google type

Unicode ⯪

(you paste the glyph you are looking for).

From the results you find https://unicode-table.com/en/2BEA/ that says that the character is called "Star with Left Half Black" and that the code is U+2BEA.

Next you take the 2BEA portion of U+2BEA and paste it into the URL below between /char/ and /fontsupport.htm

https://www.fileformat.info/info/unicode/char/2BEA/fontsupport.htm

The URL for your missing character lists all the fonts that contain that character. Now you can click "view" next to each font listed and find the one you like best. If you find multiple that you like equally well, you can download all of them and then pick the smallest one.

You want to have a .ttf, .woff, and .woff2 version of the font you choose and then you can use it in CSS as follows:

@font-face {
  font-family: 'BabelStoneShapes';
  src:  url('/fonts/BabelStoneShapes.woff2')format('woff2'), /* Smallest file, if your browser can use this, it will stop here and not download the rest */
        url('/fonts/BabelStoneShapes.woff')format('woff'),   /* A larger file, if your browser does not understand woff2 */
        url('/fonts/BabelStoneShapes.ttf')format('truetype');/* The largest of the three */
  font-weight: normal;
  font-style: normal;
  font-display: block;
}

div.rating {
  font-family: BabelStoneShapes;
}

and then use it in HTML as follows:

<div class="rating">★★★⯪☆</div>

Obviously, if Stack Overflow wanted to, they could make their website support virtually all Unicode fonts by using Symbola and updating it each time a new version came out. But they probably never will so in this "Answer" you won't see the half star, but if you follow the example, you will.

Upvotes: 0

Gangula
Gangula

Reputation: 7334

below is the Font Awesome 5 version of @Rob's answer above:

We can use font-family: "Font Awesome 5 Free"; font-weight: xxx; to switch between solid and outline

You can play around with the code at the following link.

/* rating box with fontawesome 5 inspired from - https://stackoverflow.com/a/49343426/6908282*/

.rating-box {
  position: relative;
  vertical-align: middle;
  font-size: 3em; /* comment/edit this to change size */
  font-family: FontAwesome;
  display: inline-block;
  color: #F68127;
}

.rating-box:before {
  font-family: "Font Awesome 5 Free";
  font-weight: 400;
  content: "\f005 \f005 \f005 \f005 \f005";
}

.rating-box .rating {
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
  overflow: hidden;
  color: #F68127;
}

.rating-box .rating:before {
  font-family: "Font Awesome 5 Free";
  font-weight: 900;
  content: "\f005 \f005 \f005 \f005 \f005";
}
<script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script>

<div class="rating-box">
  <div class="rating" style="width:52%;"></div>
</div>

Upvotes: 2

Dan E
Dan E

Reputation: 177

This is very nice, thanks for sharing. I made the same tweak as Faraz, switching to

<i class="fas fa-star" aria-hidden="true"></i>

in the stars-active span, and

<i class="far fa-star" aria-hidden="true"></i>

in stars-inactive, as it bothered me that stars above the rating % didn't show.

Upvotes: 1

to240
to240

Reputation: 381

For future reference, FontAwesome have added half stars to their arsenal. Make sure to include <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> in the <head> section of your page, and then the following will give you the basic structure.

    <span class="score">
<div class="score-wrap">
    <span class="stars-active" style="width:88%">
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star" aria-hidden="true"></i>
        <i class="fa fa-star-half" aria-hidden="true"></i>
    </span>
</span>
</div>

If you want the stars to appear bigger, edit fa fa-star to be fa fa-star 3x where 3x indicates the size, so 3x, 4x, 5x etc. If you would like a different style of star, use fa-star-o. The default colour is black, so if you would like to change the colour you can either edit it via CSS or add the colour to the class, i.e class="fa-star-o bg-light"

Upvotes: 1

Faraz M. Khan
Faraz M. Khan

Reputation: 159

I find myself doing with two sets of stars styles solid and regular. Solid set declared first to have higher z-index and overlapped Regular sets of stars controlled by hidden, nowrap and width.

.stars-rating {
	position: relative;
    display: inline-block;
}

.stars-rating .stars-score {
              position: absolute;
              top: 0;
              left: 0;
              overflow: hidden;
              width: 20%;
              white-space: nowrap;
}
		    <div class="stars-rating">
		    	<div class="stars-score" style="width: 20%">
		    		<i class="fas fa-star"></i>
		    		<i class="fas fa-star"></i>
		    		<i class="fas fa-star"></i>
		    		<i class="fas fa-star"></i>
		    		<i class="fas fa-star"></i>
		    	</div>
				<div class="stars-scale">
					<i class="far fa-star"></i>
					<i class="far fa-star"></i>
					<i class="far fa-star"></i>
					<i class="far fa-star"></i>
					<i class="far fa-star"></i>
				</div>
		    </div>

Upvotes: 1

Daniel Beck
Daniel Beck

Reputation: 21495

The overflow:hidden needs to be on 'stars-active' (the sized element) instead of 'score-wrap' (which never overflows.) You can use white-space: nowrap to prevent the stars from wrapping to the next line within the hidden-overflow container.

.score {
  display: block;
  font-size: 16px;
  position: relative;
  overflow: hidden;
}

.score-wrap {
  display: inline-block;
  position: relative;
  height: 19px;
}

.score .stars-active {
  color: #EEBD01;
  position: relative;
  z-index: 10;
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
}

.score .stars-inactive {
  color: grey;
  position: absolute;
  top: 0;
  left: 0;
  -webkit-text-stroke: initial;
  /* overflow: hidden; */
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" />

<span class="score">
    <div class="score-wrap">
        <span class="stars-active" style="width:88%">
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
        </span>
<span class="stars-inactive">
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
        </span>
</div>
</span>

<span class="score">
    <div class="score-wrap">
        <span class="stars-active" style="width:50%">
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
        </span>
<span class="stars-inactive">
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
        </span>
</div>
</span>

<span class="score">
    <div class="score-wrap">
        <span class="stars-active" style="width:100%">
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
        </span>
<span class="stars-inactive">
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
        </span>
</div>
</span>

<span class="score">
    <div class="score-wrap">
        <span class="stars-active" style="width:0%">
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
            <i class="fa fa-star" aria-hidden="true"></i>
        </span>
<span class="stars-inactive">
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
            <i class="fa fa-star-o" aria-hidden="true"></i>
        </span>
</div>
</span>

Upvotes: 16

Rob Monhemius
Rob Monhemius

Reputation: 5144

I found this solution by Paales here: https://github.com/FortAwesome/Font-Awesome/issues/717

I think it's an elegant solution. It looks comparable to your code because the full stars overlap the empty stars and by using overflow: hidden and position: absolute. Now you can set the width of the full stars and show partly filled stars. If you want to show half stars you could change the width of the absolute positioned element with 10% increments.

.rating-box {
  position:relative;
  vertical-align: middle;
  font-size: 3em;
  font-family: FontAwesome;
  display:inline-block;
  color: #F68127;
}
.rating-box:before{
    content: "\f006 \f006 \f006 \f006 \f006";
  }
.rating-box .rating {
    position: absolute;
    left:0;
    top:0;
    white-space:nowrap;
    overflow:hidden;
    color: #F68127;
  }
  .rating-box .rating:before {
      content: "\f005 \f005 \f005 \f005 \f005";
    }
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet" />

<div class="rating-box">
    <div class="rating" style="width:30%;"></div>
</div>

PS: Daniel Beck already gave you the answer about the mistake you made regarding white-space: no-wrap, so I suggest accepting that answer. I just wanted to share this solution because I think it is a very nice alternate approach.

Upvotes: 11

Related Questions