skip to Main Content

So I have some text which I make upright and I want to have a different background behind each letter.

For my actual use case, the list of backgrounds is randomly generated by a function that gets fed the number of letters.

Now the question is… how much vertical space does a letter occupy? I’m using a monospaced font here and I’ve set the line-height to 1 (this is a value I can pick, so I picked 1 thinking this would simplify things).

Here’s a mock Sass version of the code:

$c: #448aff, #1565c0, #009688, #8bc34a, #ffc107, #ff9800, #f44336, #ad1457;
$n: length($c);
$m: .5*$n;
$l: ();

@for $i from 0 to $m {
    $l: $l, 
        conic-gradient(from random(360)*1deg 
                at random(100)*1% random(100)*1%, 
                nth($c, $i + 1), nth($c, $i + $m + 1), 
                nth($c, $i + 1))
            0 $i*1em
}

div {
    box-shadow: 0 0 0 6px;
    background: $l;
    background-repeat: no-repeat;
    background-size: 100% 1em;
    font: 900 clamp(1em, 18vmin, 18em)/ 1 monospace;
    writing-mode: vertical-lr;
    text-orientation: upright;
    text-transform: uppercase
}

So with a line-height of 1, I would think a letter occupies 1lh or 1em… but that’s not enough!

div {
  box-shadow: 0 0 0 6px;
  background: 
    conic-gradient(from 37deg at 54% 48%, #448aff, #ffc107, #448aff), 
    conic-gradient(from 264deg at 8% 31%, #1565c0, #ff9800, #1565c0) 0 1em, 
    conic-gradient(from -61deg at 92% 2%, #009688, #f44336, #009688) 0 2em, 
    conic-gradient(from -5deg at 41% 95%, #8bc34a, #ad1457, #8bc34a) 0 3em;
  background-repeat: no-repeat;
  background-size: 100% 1em;
  font: 900 clamp(1em, 18vmin, 18em)/1 monospace;
  writing-mode: vertical-lr;
  text-orientation: upright;
  text-transform: uppercase
}
<div>play</div>

What am I missing? How much vertical space does a letter occupy in this scenario? How do I size and position my gradients so that I have one behind each letter?


Splitting the text into letters, each wrapped in an element with its own background is absolutely NOT an option here. Not interested in that.

2

Answers


  1. Playing with line-height won’t work because it will adjust the horizontal space and not the vertical one

    div {
      box-shadow: 0 0 0 6px;
      font: 900 clamp(1em, 18vmin, 18em)/4 monospace;
      writing-mode: vertical-lr;
      text-orientation: upright;
      text-transform: uppercase
    }
    <div>play</div>

    So I think you are left with the default behavior of 1.2em but not sure if you can rely on it since it depends on the font and the browser implementation

    Depends on the user agent. Desktop browsers (including Firefox) use a default value of roughly 1.2, depending on the element’s font-family. ref

    If you combine it with the use of percentage on background-position, you will have only one value to "guess" so if you know the font-family it can work.

    div {
      box-shadow: 0 0 0 6px;
      background: 
        conic-gradient(from 37deg at 54% 48%, #448aff, #ffc107, #448aff) 0 calc(0*100%/3), 
        conic-gradient(from 264deg at 8% 31%, #1565c0, #ff9800, #1565c0) 0 calc(1*100%/3), 
        conic-gradient(from -61deg at 92% 2%, #009688, #f44336, #009688) 0 calc(2*100%/3), 
        conic-gradient(from -5deg at 41% 95%, #8bc34a, #ad1457, #8bc34a) 0 calc(3*100%/3);
      background-repeat: no-repeat;
      background-size: 100% 1.2em; /* you will have to adjust this */
      font: 900 clamp(1em, 18vmin, 18em)/1 monospace;
      writing-mode: vertical-lr;
      text-orientation: upright;
      text-transform: uppercase
    }
    <div>play</div>

    Edit: as per @Ana comment, we can also use percentage for the size and no more depend on font metrics

    div {
      box-shadow: 0 0 0 6px;
      background: 
        conic-gradient(from 37deg at 54% 48%, #448aff, #ffc107, #448aff) 0 calc(0*100%/3), 
        conic-gradient(from 264deg at 8% 31%, #1565c0, #ff9800, #1565c0) 0 calc(1*100%/3), 
        conic-gradient(from -61deg at 92% 2%, #009688, #f44336, #009688) 0 calc(2*100%/3), 
        conic-gradient(from -5deg at 41% 95%, #8bc34a, #ad1457, #8bc34a) 0 calc(3*100%/3);
      background-repeat: no-repeat;
      background-size: 100% calc(100%/4); 
      font: 900 clamp(1em, 18vmin, 18em)/1 monospace;
      writing-mode: vertical-lr;
      text-orientation: upright;
      text-transform: uppercase
    }
    <div>play</div>

    This said, you can create the same thing differently. A bit hacky but it can be a good workaround:

    div {
      width: 1ch; /* limit the width to one character */
      word-break: break-all; /* allow the word to break */
      /* you can use 1lh everywhere */
      background: 
        conic-gradient(from 37deg at 54% 48%, #448aff, #ffc107, #448aff), 
        conic-gradient(from 264deg at 8% 31%, #1565c0, #ff9800, #1565c0) 0 1lh, 
        conic-gradient(from -61deg at 92% 2%, #009688, #f44336, #009688) 0 2lh, 
        conic-gradient(from -5deg at 41% 95%, #8bc34a, #ad1457, #8bc34a) 0 3lh;
      background-repeat: no-repeat;
      background-size: 100% 1lh;
      /* you can use percentage with background-position as well
      background-position:
       0 calc(0*100%/3),
       0 calc(1*100%/3),
       0 calc(2*100%/3),
       0 calc(3*100%/3); */
      font: 900 clamp(1em, 18vmin, 18em)/1 monospace;
      
      display: inline-block;
      margin: 5px;
      padding-inline: .2em;
      box-shadow: 0 0 0 6px;
      vertical-align: top;
      text-transform: uppercase
    }
    <div>play</div>
    <div style="line-height: 2">play</div>
    <div style="line-height: .9">play</div>
    Login or Signup to reply.
  2. Using word-break also works, especially if you want to keep the gradient backgrounds square with larger line heights.

    div {
    box-shadow: 0 0 0 6px;
    background: 
        conic-gradient(from 37deg at 54% 48%, #448aff, #ffc107, #448aff) 0 calc(0 * 100% / 3),
        conic-gradient(from 264deg at 8% 31%, #1565c0, #ff9800, #1565c0) 0 calc(1 * 100% / 3),
        conic-gradient(from -61deg at 92% 2%, #009688, #f44336, #009688) 0 calc(2 * 100% / 3),
        conic-gradient(from -5deg at 41% 95%, #8bc34a, #ad1457, #8bc34a) 0 calc(3 * 100% / 3);
    background-repeat: no-repeat;
    background-size: 100% calc(100% / 4);
    font: 900 clamp(1em, 18vmin, 18em) / 1.5 monospace;
    text-transform: uppercase;
    padding-inline: calc((1lh - 1em) / 2);
    width: 1em;
    text-align: center;
    word-break: break-all;
    }
    <div>play</div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search