Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS Partially Filled Stars and Spacing

Tags:

html

css

I'm using HTML and CSS to show a star rating based on a percentage. I'm trying to get that percentage to match the percentage of the stars filled.

I have it close, but when I add the 'letter-spacing' and 'padding-left' CSS to make it look better on my web page, the percentage of the filled area changes.

Here is my HTML and CSS:

.score {
  margin-bottom: 5px;
  display: inline-block;
  font-size: 40px;
  color: #ccc;
  position: relative;
  text-shadow: 0px 0px 4px #FFF;
}

.score::before,
.score span::before {
  content: "✰✰✰✰✰";
  display: block;
}

.score span {
  color: #E6DB74;
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
}

.scorePadded {
  margin-bottom: 5px;
  display: inline-block;
  font-size: 40px;
  color: #ccc;
  position: relative;
  text-shadow: 0px 0px 4px #FFF;
  letter-spacing: 20px;
  padding-left: 5px;
}

.scorePadded::before,
.scorePadded span::before {
  content: "✰✰✰✰✰";
  display: block;
}

.scorePadded span {
  color: #E6DB74;
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  padding-left: 5px;
}

body {
  background: black;
}
<div>
  <span class="score"><span style="width: 68.0%"></span></span>
</div>
<div>
  <span class="scorePadded"><span style="width: 68.0%"></span></span>
</div>

I'd like to make the bottom stars (with the spacing) filled to the same percentage as the top stars (which I believe is correctly showing a 68% fill), but the spacing isn't allowing that.

like image 357
mainstringargs Avatar asked Jul 19 '19 18:07

mainstringargs


People also ask

How do you show half stars in CSS?

Just set . star width to 24 and . star. half:after margin-left to -24px, width to 12px, and the half-stars will render correctly.

How do you make a dynamic star rating?

Go to the settings panel on the left side. Click the dynamic icon on the Rating field under the Rating block and select ACF Number Field. Click the wrench icon on the ACF Number Field field and select the key (custom field) you have created on step one above. You can add a prefix on the Title field.


1 Answers

The gaps make this a bit more complex than a simple percentage. I don't believe there's a CSS solution that can account for the gaps, so that the fill is applied explicitly to the stars themselves.

That said, with a bit of math, you could apply the correct width with a formula.

As I see it, you need to take your rating and multiply it by the width of a star. This tells us how much to fill, in pixels. E.g., rating * starWidth, where rating is out of 5.

You then need to add for each gap. The amount of gaps the score crosses can be expressed as Math.floor(rating). To get the width in pixels, it's Math.floor(rating) * gapSize. This is how many pixels we have to add to account for the large gaps, ensuring that when we get to one, we start filling the next star instead of the gap between them.

By adding the fill width and the gap width, you get this:

totalWidthInPixels = (rating * starWidth) + (gaps * gapSize);

Seeing as you mentioned you're calculating this percentage using Jekyll, and I don't know anything about Jekyll, I'll let you fill in that part.

A demonstration of the formula can be seen below.

const span1 = document.getElementById("score");
const span2 = document.getElementById("scorePadded");

const rating = parseFloat(prompt("Enter rating between 0-5"));
const starWidth = span1.offsetWidth / 5.0;
const gapSize = (span2.offsetWidth - span1.offsetWidth - 5) / 5.0;
const gaps = Math.floor(rating);

const width = (rating * starWidth) + (gaps * gapSize);

span1.style.width = `${(rating/5) * 100}%`;
span2.style.width = `${width}px`;

console.log("star width: ", starWidth);
console.log("gap size: ", gapSize);
console.log("fill width: ", width);
.score {
  margin-bottom: 5px;
  display: inline-block;
  font-size: 40px;
  color: #ccc;
  position: relative;
  text-shadow: 0px 0px 4px #FFF;
}

.score::before,
.score span::before {
  content: "✰✰✰✰✰";
  display: block;
}

.score span {
  color: #E6DB74;
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
}

.scorePadded {
  margin-bottom: 5px;
  display: inline-block;
  font-size: 40px;
  color: #ccc;
  position: relative;
  text-shadow: 0px 0px 4px #FFF;
  letter-spacing: 20px;
  padding-left: 5px;
}

.scorePadded::before,
.scorePadded span::before {
  content: "✰✰✰✰✰";
  display: block;
}

.scorePadded span {
  color: #E6DB74;
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  padding-left: 5px;
}

body {
  background: black;
}
<div>
  <span class="score"><span id="score"></span></span>
</div>
<div>
  <span class="scorePadded"><span id="scorePadded"></span></span>
</div>
like image 200
Tyler Roper Avatar answered Sep 30 '22 13:09

Tyler Roper