cssline-height

CSS line height does not go all the way up or down


I have a problem that I've had for years.

A text with line-height: 1 will be compact and will reach the top and bottom of the surrounding elements.

A text with another line-height will be more readable but at the same time, it will no longer reach the top and bottom of the surrounding elements.

Here is a code example of the problem and a hackish solution. Changing the line-height or the font size will break it.

Is the a solid fix for this?

.wrap {
  display: flex;
}

.first {
  background: red;
  width: 1rem;
}

.second,
.second2{
  line-height: 2;
}

.second2 {
  margin-top: -9px;
  margin-bottom: -7px;
}
<strong>Problem:</strong> The letter "A" does not align with the red top.<br><br>

<div class="wrap">
  <div class="first"></div>
  <div class="second">A text that<br>spans on multiple rows</div>
</div>

<br><br>

<strong>Hackish fix:</strong> The letter "A" does align with the red top.<br><br>

<div class="wrap">
  <div class="first"></div>
  <div class="second2">A text that<br>spans on multiple rows</div>
</div>

The line-height is taken to the extreme, just to show the effect.


Solution

  • As you've observed, if you give an element containing text:

    the text will be rendered in the vertical middle of the line-height.

    The text will still be 1em tall, but it will now have 0.5em of space above it and below it.

    To (seemingly, though not actually) counteract this vertical-middle-alignment, one approach would be to apply a

    transform: translateY(-0.5em)
    

    to the text-containing element.


    Working Example:

    body {
      display: flex;
    }
    
    .wrap-1,
    .wrap-2,
    .wrap-3 {
      display: flex;
      margin-right: 12px;
    }
    
    .first {
      background: red;
      width: 1rem;
    }
    
    .wrap-1 .second {
      font-size: 1em;
      line-height: 1em;
      background-color: rgb(255, 255, 0);
    }
    
    .wrap-2 .second {
      font-size: 1em;
      line-height: 2em;
      background-color: rgb(255, 255, 0);
    }
    
    .wrap-3 .second {
      font-size: 1em;
      line-height: 2em;
      background-color: rgb(255, 255, 0);
    }
    
    .wrap-3 .second p {
      background-color: rgba(0, 0, 0, 0.2);
      transform: translateY(-0.5em);
    }
    
    p {
      margin: 0;
      padding: 0;
      background-color: rgba(0, 0, 0, 0.2);
    }
    <div class="wrap-1">
      <div class="first"></div>
      <div class="second"><p>A text that<br>spans on multiple rows</p></div>
    </div>
    
    <div class="wrap-2">
      <div class="first"></div>
      <div class="second"><p>A text that<br>spans on multiple rows</p></div>
    </div>
    
    <div class="wrap-3">
      <div class="first"></div>
      <div class="second"><p>A text that<br>spans on multiple rows</p></div>
    </div>