CSS gradient fill text in :before on separate line

Viewed 44

I'm trying to use CSS to create a "5-star rating", but need the stars to be on the line before the text. My starting point is the last of the 5 methods in Five Methods for Five-Star Ratings on CSS Tricks. Basically, it assigns a rating number as a CSS variable, then uses that to calculate a gradient fill on the stars, which are unicode characters in a :before tag.

The problem is, I need the stars to be on a separate line from the main text.

He has the whole div set to display: inline-block:

:root {
  --star-color: #fff;
  --star-background: #fc0;
}

.Stars {
  --percent: calc(var(--rating) / 5 * 100%);
  
  display: inline-block;
  line-height: 1;
  
  &::before {
    content: '★★★★★';
    letter-spacing: 3px;
    background: linear-gradient(90deg, var(--star-background) var(--percent), var(--star-color) var(--percent));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}

and the HTML:

<div class="stars" style="--rating: 2.3;"></div>

Various things I've tried to get the stars on their own line:

  • Change the :before to display: block
  • Change the :before to display: block; background-size: 100%
  • Change the <div> to display: flex; flex-direction: column
  • Add the '\A' escape character to the :before content

All of the above result in the background not aligning with the star-text in various different ways, the most interesting being when the text is centered, which is my actual use case.

Any ideas on how to accomplish this?

Snippet:

:root {
  --star-color: #fff;
  --star-background: #fc0;
}

.Stars {
  --percent: calc(var(--rating) / 5 * 100%);
  
  display: inline-block;
  line-height: 1;
  width: 100%;
}

.Stars:before {
    content: '★★★★★';
    
    letter-spacing: 3px;
    background: linear-gradient(90deg, var(--star-background) var(--percent), var(--star-color) var(--percent));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.centered {
    text-align: center;
}

.two-line:before {
    display: block;
}
<h1>Working</h1>
<div class="Stars" style="--rating: 4;">4 stars!</div>

<div class="Stars" style="--rating: 2.5;">2.5 stars. Meh.</div>

<div class="Stars" style="--rating: 1.5;">1.5 stars. Doh!</div>

<div class="Stars centered" style="--rating: 4;">4 stars!</div>

<div class="Stars centered" style="--rating: 2.5;">2.5 stars. Meh.</div>

<div class="Stars centered" style="--rating: 1.5;">1.5 stars. Doh!</div>

<h1>Not Working</h1>
<div class="Stars two-line" style="--rating: 4;">4 stars!</div>

<div class="Stars two-line" style="--rating: 2.5;">2.5 stars. Meh.</div>

<div class="Stars two-line" style="--rating: 1.5;">1.5 stars. Doh!</div>

<div class="Stars centered two-line" style="--rating: 4;">4 stars!</div>

<div class="Stars centered two-line" style="--rating: 2.5;">2.5 stars. Meh.</div>

<div class="Stars centered two-line" style="--rating: 1.5;">1.5 stars. Doh!</div>

1 Answers

Update this style!

.two-line:before {
   display: inline-block;
}
Related