60

This question's answer says that the font-size defines the height of a box so that all letters (with ascenders and descenders) can fit.

But why has a span with 40px font-size and line-height an actual size of 45px? If I understand the linked question correctly then "X" should be smaller than 40px but the overall height should be exactly 40px. I thought that maybe it is making some extra room above/below the ascenders/descenders but the image shows that the ascenders/descenders take all the space so there can't be much extra room:

enter image description here

When I wrap a div (green) around the span then the div has a height of 40px. Why does the div use the font-size of its child for its height but the child itself doesn't?:

enter image description here

Now when I set the span's line-height to 15px (less than the font-size) then the div's height changes to 26px. How is this value calculated? Has this something to do with the baseline?:

enter image description here

When I set the span's line-height to 65px (more than the font-size) then the div's height is the height of the line-height. I would have expected the div's height to be something like (65px - 45px) + 45px.:

enter image description here

So how do font-size and line-height affect the actual heights of elements? I read some questions that referenced the spec but I couldn't make much out of it. Are there any easy to understand rules?

JSFiddle

user764754
  • 3,865
  • 2
  • 39
  • 55
  • Can I add a reference ([Deep dive CSS: font metrics, line-height and vertical-align](https://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align)) I found for your question... – samm Mar 02 '20 at 14:04

2 Answers2

54

First, I recommend reading my answer in Inline elements and line-height. To summarize, there are various heights related to inline boxes:

  • Height of the inline box, given by line-height
  • Height of the line box, which in simple cases is also given by line-height, but not here.
  • Height of the content area of the inline box, which is implementation dependent. This is the area painted by the red background.

The other height in your case is the height of the parent div. This is determined by §10.6.3. In this case, since the box establishes an inline formatting context with one line,

The element's height is the distance from its top content edge to [...] the bottom edge of the last line box

So the height of the parent block is given by the height of the line box.

What happens here is that the height of the line box is not the line-height of your inline box. And that's because the line-height of the parent block is also taken into account:

On a block container element whose content is composed of inline-level elements, 'line-height' specifies the minimal height of line boxes within the element.

The minimum height consists of a minimum height above the baseline and a minimum depth below it, exactly as if each line box starts with a zero-width inline box with the element's font and line height properties.

We call that imaginary box a "strut."

If you set parent's line-height to 0, and child's vertical-align to e.g top, then the height of the parent will exactly be the line-height of the child.

.outer {
  margin-top: 50px;
  background-color: green;
  width: 150px;
  font-family: "Times New Roman";
  line-height: 0;
}
.letter-span-1 {
  background-color: red;
  line-height: 40px;
  font-size: 40px;
  vertical-align: top;
}
.letter-span-2 {
  background-color: red;
  line-height: 15px;
  font-size: 40px;
  vertical-align: top;
}
.letter-span-3 {
  background-color: red;
  line-height: 65px;
  font-size: 40px;
  vertical-align: top;
}
<span class="letter-span-1">XxÀg</span>
<div class="outer">
  <span class="letter-span-1">XxÀg</span>
</div>
The parent block is 40px tall.
<div class="outer">
  <span class="letter-span-2">XxAg</span>
</div>
The parent block is 15px tall.
<div class="outer">
  <span class="letter-span-3">XxÀg</span>
</div>
The parent block is 65px tall.

If you don't set a line-height to the parent, it will be normal.

Tells user agents to set the used value to a "reasonable" value based on the font of the element[...]. We recommend a used value for 'normal' between 1.0 to 1.2.

That means that there will be a minimum height for the parent which will be its font-size (which you don't specify, and the default is implementation-dependent) multiplied by that factor (implementation-dependent).

You should also consider the vertical-align of the span. By default it's baseline, and that may create a gap below. The image in web-tiki's answer is especially useful:

enter image description here

That's because vertical-align determines how the span will be aligned with the strut, and with baseline the alignment can depend on font-size and end up increasing the height of the line box. The line box height is the distance between the top of the uppermost and the bottom of the lowermost boxes in the line.

If you don't want the height of the parent div to be increased by that, you need some other vertical-align, like top, middle, or bottom. Then the font-size of the span shouldn't affect the height of the div.

To summarize, the height of the div depends on

  • Its line-height
    • ... which by default depends on div's font-size
  • Span's line-height
    • ... which by default depends on span's font-size
  • Possibly span's font-size, depending on span's vertical-align
  • And obviously height, min-height, max-height, etc.
Community
  • 1
  • 1
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • So the span's 45px (instead of 40px) come from the fact that it's implementation dependent and it's simply not exact? Also in my sample are only inline boxes and no line boxes, right? – user764754 Dec 26 '16 at 22:09
  • @user764754 Yes, the height of the red area is implementation dependent. Inline boxes are always wrapped in line boxes, there is a line box in your example. – Oriol Dec 26 '16 at 22:11
  • So you say that the div height depends on the div + span line-height . But when I change the .letter-span-2 font-size to 12px then the div height changes from 26px to 20px although the div + span line-heights are still the same? Or does changing the font-size somehow change the div line-height? – user764754 Dec 26 '16 at 22:23
  • @user764754 `vertical-align` also plays a role, which affects how the span will be aligned with respect to the strut. The default `baseline` adds some additional space which may depend on the `font-size`. If you use `vertical-align: top`, then the `font-size` of the span shouldn't affect the height of the div. – Oriol Dec 26 '16 at 22:36
  • See [Image inside div has extra space below the image](http://stackoverflow.com/q/5804256/1529630) – Oriol Dec 26 '16 at 22:43
  • I think it would be really great if you could write a simplified version below your actual answer (maybe based on the questions in my comments). – user764754 Dec 26 '16 at 22:44
  • Awesome answer, I wish I could upvote more than once. Thanks! :) – Zaphoid Mar 21 '22 at 21:12
6

Introduction

Good question,

I learn most of these things through personal experience.

In this case, the DIV height is set to auto. It will detect the height of its own contents, and evaluate its new height from there.

Clearly, the DIV only takes into account the line height of the . This is likely due to the diverse number of fonts. Line-height gives us the adaptability we need for various font types.

In Short

font-size

Font size only changes the actual font itself, and not the div elements around it

line-height

Line-height is the height of the actual line and will change the div elements around it

Wait a second...

If we have something like this:

div {
  background: green;
  margin-top: 50px;
}
.test-one {
  font-size: 20px
}
.test-two {
  font-size: 40px
}
<div>
  <span class="test-one"> test one </span>
</div>

<div>
  <span class="test-two"> test one </span>
</div>

Clearly the size of the DIV (height: auto;) changes according to font-size. That's because the line-height will automatically adjust accordingly if it is not set manually.

One Exception

Upon further inspection, I noticed that DIVs don't always match the line-height. This occurs if the line-height is very small, and the font exceeds it by some distance.

The example you gave -

.outer {
  margin-top: 50px;
  background-color: green;
  width: 150px;
  font-family: "Times New Roman"
}
.letter-span-1 {
  background-color: red;
  line-height: 40px;
  font-size: 40px;
}
.letter-span-2 {
  background-color: red;
  line-height: 15px;
  font-size: 40px;
}
.letter-span-3 {
  background-color: red;
  line-height: 65px;
  font-size: 40px;
}
<span class="letter-span-1">XxÀg</span>

<div class="outer">
  <span class="letter-span-1">XxÀg</span>
</div>

<div class="outer">
  <span class="letter-span-2">XxÀg</span>
</div>

<div class="outer">
  <span class="letter-span-3">XxÀg</span>
</div>

If you look closely,

letter-span-1 and letter-span-3 both result in the DIV equaling the line-height.

However, letter-span-2 does not.

-------------- Line-height - Actual-height

letter-span-1: 40px - 40px

letter-span-2: 15px - 25px

letter-span-3: 65px - 65px

Notice that letter-span-2 is the smallest. It is so small, it will actually limit the height of the div. You can test this by altering the font size.

The "Why?"

Why have these two different settings, and not just change height normally?

I honestly am not sure, but I speculate that it was because fonts aren't standard. If the computer misreads a particular font, it may incorrectly evaluate the line-height.

Not to mention the numerous "CSS Tricks" you can do with line-height. It is great for adding space for open designs.

Conclusion

Line-height defines div height, unless line-height is very small, in which case the font-size will define the size.

Jacob
  • 890
  • 10
  • 30
  • Yes the line-height changes if you don't set it explicity. But I don't quite think that the div "only takes into account the line height of the" span. I think my samples showed that there are different outcomes for: `line-height` lt/eq/gt `font-size`. – user764754 Dec 26 '16 at 21:52
  • Aha, you're right. I found out what that was. I'm going to update it. – Jacob Dec 26 '16 at 22:13
  • Your answer is helpful but it doesn't really explain why a 40px font-size and line-height span has a height of 45px or what the actual logic is behind .letter-span-2 being so small that it will somehow limit the div height. So I'm only gonna upvote for now. – user764754 Dec 26 '16 at 22:36
  • I'll clarify a bit better – Jacob Dec 26 '16 at 22:41
  • Does that make sense? It usually is the line-height defining the height, but sometimes the font-size will take over. – Jacob Dec 26 '16 at 22:49