Why is there space between line boxes, not due to half leading?

In the code example below, you will see white-space between the vertically flowing spanss. The white space is between each line box.

I want to start out by stating that this has nothing to do with gaps between inline-block boxes or even a result of half leading, which is added on top and bottom of an inline level box when calculating minimum line height.

From the CSS2.1 spec:

The height of the inline box encloses all glyphs and their half-leading on each side and is thus exactly 'line-height'.

And:

The minimum height (of a line box) consists of a minimum height above the baseline and a minimum depth below it....

Notes:

  • background-color (as seen in the below example) covers the full line box
  • Despite that, there is still white-space between each line box
  • I am not asking for a solution to remove the gap. If I wanted to do that, I would just set display: inline-block on the span

Why is the gap there, with basis in the CSS2.1 specification. What part of the spec explains that spacing?

Example code:

// From CSS spec:
// The height of the inline box encloses all glyphs and their half-leading on each side and is thus exactly 'line-height'. Boxes of child elements do not influence this height.
span {
  background-color: red;
  line-height: 1;
}
<span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>

The background properties applies only to the content area and not the line box. In most of the cases the content area is defined by the height. As we can read in the specification:

The dimensions of the content area of a box — the content width and content height — depend on several factors: whether the element generating the box has the 'width' or 'height' property set, whether the box contains text or other boxes, whether the box is a table, etc.

And here:

This property specifies the content height of boxes.

This property does not apply to non-replaced inline elements. See the section on computing heights and margins for non-replaced inline elements for the rules used instead.

And if check the above link we can read:

The 'height' property does not apply. The height of the content area should be based on the font, but this specification does not specify how. A UA may, e.g., use the em-box or the maximum ascender and descender of the font.

Here is an illustration to better show youref:

Location of the baseline on text

The content area is defined by the browser and in some case it can be the em1 that you see in above figure but not necessarely.

In all the cases and whataver the line-height will be, the content area will only depend on the font properties. So the line-height define the height of the line box AND the content area height is defined by the font properties.

So the real question is: Why by default the line-height doesn't make the line box equal to the content-area?

If check we check the documentation we can see that the default value is set to normal and:

normal

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

Then

<number> (unitless)

The used value is this unitless <number> multiplied by the element's own font size.

In some cases, we will have the line box a bit bigger than the content area which explain the gap.1


Now why setting the line-height to 1 doesn't fix the issue?

Simply because you set the line-height of the spans and not the line-height of their container which is not enough. The line-height of the container is still the default one 1.2 which will be considered since it's bigger than 1. In other words, the biggest line-height will win.

Here is some illustration to better understand:

line-height of the body is 2 and only a bigger line-height for span will have an effect:

body {
 line-height:2
}

span {
  background-color: red;
  line-height: 1;
  animation:change linear infinite 2s alternate;
}

@keyframes change {
  to {line-height:3}
}
<span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>

Setting line-height to body is enough as the span will inherit it:

body {
 line-height:1; /*line-height is equal to content area*/
}

span {
  background-color: red;
}
<span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>

1 Worth to note that in some cases and for some particular font, you may not see any gap and you won't even need to set line-height to 1 because the content area may be bigger enough to cover the line box since the calculation of both value are independent.

Here is some examples

span {
  background-color: red;
}
div {
 margin:5px;
}
<div><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>
<div style="font-family:cursive"><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>

<div style="font-family:monospace"><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>

<div style="font-family:sans-serif"><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>

We have gaps only for the first and last example.


It's because the parent container's line height does not match the span's - line height affects the children so as span is inline, it is obeying the parent's line height

// From CSS spec:
// The height of the inline box encloses all glyphs and their half-leading on each side and is thus exactly 'line-height'. Boxes of child elements do not influence this height.
div {
  line-height: 1;
}
span {
  background-color: red;
  line-height: 1;
}
<div>
<span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>