Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding CSS2.1 specification regarding height on inline-level boxes

Tags:

html

css

CSS2.1 Section 10.6.1 specifies:

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.

The vertical padding, border and margin of an inline, non-replaced box start at the top and bottom of the content area, and has nothing to do with the 'line-height'.

Then, the statements that seem contradictory follow in 10.8 Line height calculations:

The height of a line box is determined as follows:

  1. The height of each inline-level box in the line box is calculated. For inline boxes, this is their 'line-height'....

And:

User agent must align glyphs in a non-replaced inline box to each other by their relevant baselines....

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

There is something I am not fully understanding here.

Is the height of inline-level boxes equal to the line-height property set on them (with the minimum being the line-height set on the parent block container element), OR is it just determined by the font height (and UA implementation)?


EDIT

Just to avoid confusion (since there are many posts about this):

  • I know that an inline-level element's content height is equal to the font it contains (and UA implementation)
  • I realize the spec does state that in 10.6.1, but in 10.8.1 it states that the height of an inline-level box is equal to its line-height
  • That seems contradictory to me
  • My purpose with this post is to discuss the wording in the spec, in order to fully understand what it means and how it ties in with reality

EDIT:

To avoid the "opinion based" close votes, I have changed the title. It is not my opinion that the spec is contradictory, and I am not asking for anyone else's opinion on whether it is contradictory either.

I realize it is not actually contradictory, I was just trying to understand why it is not, given its wording.

like image 644
Magnus Avatar asked Sep 11 '18 18:09

Magnus


2 Answers

Is the height of inline-level boxes equal to the line-height property set on them (with the minimum being the line-height set on the parent block container element),

Yes it is.

OR is it just determined by the font height (and UA implementation)?

No it isn't

CSS is really about boxes, not elements, and you should try not to confuse the two.

So an inline element has associated with it a number of boxes. A content box, padding box, border box and margin box. It also has zero (if display:none), one, or multiple inline boxes. The content box, paddings, borders and margins may be divided among the inline boxes so that the inline content can be spread over more than one line.

The inline box's height is the content height adjusted by the leading. It's the leading that does the magic here. The leading is defined as the line-height of the element minus the content height of that inline box.

Simply rearranging that equation tells us that the height of the inline box depends only on the line-height and not on the content box (or padding, border, margin boxes).

Note that none of the above discusses the line box, which is a different thing again and not a direct property of inline elements or their boxes. The line box is constructed by arranging the inline boxes that occur on the same line such that their vertical alignments fit the rules computed for the elements, including the zero width inline box formed by the strut.

Each line box is bounded by the top of uppermost inline box and the bottom of the lowestmost inline box that that line box contains.


Digression: On why the height of the line box can surprise.

Suppose we have a simple case of a containing block which just contains one short inline element (i.e. short enough that it fits in a single line box). Also suppose that everything is aligned on the baseline. Let's say that the line-height is set on the containing box to 20px, and the inline element inherits that. Also suppose that the font-size (em-square) of the containing block is 16px, and that means that the font metrics compute to an ascent (above the baseline) of 14px and a descent (below the baseline) of 4px.

So the content area for the strut is (14px + 4px =) 18px high. The line-height is 20px, so there is 2px leading, 1px goes above the ascent, and 1px below the descent. So the line-height of the strut is made of 15px above the baseline and 5px below the baseline.

Now, suppose that the font-size of the inline element is set to 0.5em (i.e. half that of the containing block). The content area for the inline element will be an ascent of 7px and a descent of 2px. The line-height is still 20px, so the leading is 20px - (7px + 2px) = 11px, meaning that 5.5px goes above the ascent and 5.5px goes below the descent. This results in the line-height for the inline element is made of 12.5px above the baseline and 7.5px below the baseline.

Since the strut and the inline element are aligned vertically to their baselines, the top of the uppermost inline box (the strut) is 15px above the baseline and the bottom of the the lowermost inline box (the inline element) is 7.5px below the baseline, the actual height of the line box is not 20px but (15px + 7.5px =) 22.5px.

like image 87
Alohci Avatar answered Nov 13 '22 17:11

Alohci


As I explained in this previous question (Why is there space between line boxes, not due to half leading?) we have the content area and the line box.

The content area is defined by the font properties and the UA (like described in your first quote) and the line box is defined by the line-height (like described in your second quote). Here is some example to show different height of content area based on different fonts and to illustrate the difference with the line box:

span {
  border-left: 1em solid red;
  background: rgba(255, 0, 0, 0.2);
}

.container>div {
  margin-bottom: 5px;
  border: 1px solid;
  line-height: 30px;
}

.container>div:nth-of-type(1) span{
  font-family: arial;
  font-size: 25px;
}

.container>div:nth-of-type(2) span{
  font-family: "open sans";
  font-size: 20px;
}

.container>div:nth-of-type(3) span{
  font-family: monospace;
  font-size: 30px;
}

.container>div:nth-of-type(4) span{
  font-family: cursive;
  font-size: 22px;
}
<div class="container">
  <div>
    <span>Hello World</span>
  </div>
  <div>
    <span>Hello World</span>
  </div>
  <div>
    <span>Hello World</span>
  </div>
  <div>
    <span>Hello World</span>
  </div>
</div>

As you can see the background and border apply to the content area that is defined by the font-family and font-size. For all the cases, I set the line-height to be equal 30px thus all the line boxes are equal.

We can also notice that the border-left behave differently which indicates that indeed the height of the content area depends on the font and UA.


Here is the same example with some vertical padding/margin/border in order to illustrate how they affect the content area and has nothing to do with line-height:

span {
  border-left: 1em solid red;
  background: rgba(255, 0, 0, 0.2);
  font-family: arial;
  font-size: 25px;
}

.container>div {
  margin-bottom: 5px;
  border: 1px solid;
  line-height: 40px;
}

.container>div:nth-of-type(1) span {
  padding: 10px;
}

.container>div:nth-of-type(2) span {
  border-bottom: 5px solid red;
}

.container>div:nth-of-type(3) span {
  padding: 10px;
  background-clip: content-box;/*I limit the background to content-box only*/
}

.container>div:nth-of-type(4) span {
  margin: 20px;
}
<div class="container">
  <div>
    <span>Hello World</span>
  </div>
  <div>
    <span>Hello World</span>
  </div>
  <div>
    <span>Hello World</span>
  </div>
  <div>
    <span>Hello World</span>
  </div>
</div>
like image 33
Temani Afif Avatar answered Nov 13 '22 17:11

Temani Afif