5

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.

Magnus
  • 6,791
  • 8
  • 53
  • 84
  • ping this user https://stackoverflow.com/users/42585/alohci or this one https://stackoverflow.com/users/106224/boltclock ... I think they are the only one that can help you with this ;) – Temani Afif Sep 11 '18 at 19:10
  • Hey Temani. Is it possible to tag them in you think? Perhaps this works: @boltclock – Magnus Sep 11 '18 at 19:11
  • 1
    no the @ works only if they already interacted with the post ... for boltclock you can tag him in this chat room https://chat.stackoverflow.com/rooms/29074/html-css-webdesign ... for Alohci, he will probably answer this alone, if not comment on one of his answers – Temani Afif Sep 11 '18 at 19:13
  • @TemaniAfif Done, let's see if he has time to stop by :) – Magnus Sep 11 '18 at 19:22
  • The first quote mentions the content area, which the second quote deals with the height of the element itself. Those are different things. Two spans below one another can easily have overlapping content areas. – Mr Lister Sep 11 '18 at 19:28
  • @MrLister Thanks for chiming in. Height of "element itself" is not well defined. The height of an element is either the height of its `content box`, `border box`, `padding box` or `margin box`. I suspect the second part really means the height of the *line box*, but is poorly worded. If the *line box* of the parent *block-level box* and child *inline-level box* is set to be smaller than em-square (font height) via `line-height` properties on both of them, the two *line boxes* will overlap as you say. – Magnus Sep 11 '18 at 20:07
  • @MrLister Also, we know that if vertical `padding`/`border`/`margin` is set taller than the containing *line box* height (which in turn is set with the `line-height` property), the `padding`/`margin`/`border box` bleeds onto surrounding content. – Magnus Sep 11 '18 at 20:12
  • @TemaniAfif Agreed. It is frustrating with close/down votes without an explanation. – Magnus Sep 11 '18 at 21:16
  • @TemaniAfif Unfortunately I have the same experience. But more so on html / css topics than JS / other OOPs. – Magnus Sep 11 '18 at 21:21
  • you don't need to change the title, I don't see any opinion based in the initial one ... unfortunatly the closes votes are random and following the first one. If this get closed I will bring it to meta and I will get in touch with each person who voted so they can explain us how? ... And I am pretty sure there is at least 2 voters not even active within the CSS tag. – Temani Afif Sep 12 '18 at 12:07
  • @TemaniAfif Yeah, that makes sense. Loop me in ;) – Magnus Sep 12 '18 at 13:36
  • Contrarily, I think the edit to the question and title *were* needed. I initially started to vote to close under the custom reason that this appeared to just be a complaint to the W3C and a request that they change their spec, and that spec changes should be posted as Issues or PRs in the W3C GitHub project. However, I decided to just go with POB for simplicity. Magnus' edit from 4 hours ago changes that, so I have removed my close vote. The question has already survived the close vote queue, so unless someone else visits this page organically and decides to close it, the others will age away. – TylerH Sep 12 '18 at 14:18
  • @TylerH Thanks for sharing your reasoning, glad I was able to clarify it. – Magnus Sep 12 '18 at 14:20
  • @Magnus As for a lack of explanation, this site has a long history of seeing retaliation and/or harassment against downvoters and closevoters when they provide an explanation for their vote, so many users have made it a habit to always do so silently. – TylerH Sep 12 '18 at 14:28

2 Answers2

4

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.

Alohci
  • 78,296
  • 16
  • 112
  • 156
  • but if we consider the trivial/simple case where we have only one inline-element and no vertical-alignment involved or anything else, can we say that the line-height define the height of the line-box? .. I think yes ... – Temani Afif Sep 11 '18 at 22:59
  • @TemaniAfif - The line height of what? There's always at least two line-heights in play - the line height of the containing block, which determines the line-height of the strut inline box, and the line height of the inline box that is part or whole of the inline element. These two combined define the height of the line box. – Alohci Sep 11 '18 at 23:04
  • yes of course, I meant in the case where both are equal .. like in my answer, I defined the line-height on the containing block and this one will be inherited so it's like we deal with *one* line-height to make it easier to explain and I meant that line-height. – Temani Afif Sep 11 '18 at 23:10
  • Got it, thank you. I'll have to chew on it a bit, but I think it makes sense to me. Follow-ups: 1) Each inline-level element is automatically enclosed in one or more anonymous inline-level boxes? More than one if they cover more than one line (box)? 2) Are inline-level boxes and inline boxes the same thing? – Magnus Sep 11 '18 at 23:15
  • 1
    @Magnus 1) I'd prefer "divided between" rather than "enclosed in" but yes. 2) not really. An inline-block element with form a single inline-level box, but has its own rules over how its content/padding/border affects the line box. – Alohci Sep 11 '18 at 23:22
  • @TemaniAfif - I'm trying to be really precise here, because both you and the question merit it. The leading is divided 50/50 above the ascender/below the descender, which I think means that if the font of the containing block, and the font of the inline element have significantly different placed baselines, the height of the line box can still be larger than the single line-height value defined. – Alohci Sep 11 '18 at 23:30
  • True, I was also thinking why the height wasn't exactly equal to line-height ... If I set the line-height to 40px or 41px I end with a height of 44px and a some headaches :p – Temani Afif Sep 11 '18 at 23:37
  • 1
    @Magnus: 1) The inline box that's generated by an inline element is not anonymous - it's its principal box, and declarations targeting the inline element will apply directly to the inline box. An inline box can be split across lines (either by wrapping or by having a block-level box "inside" it), but it's still one inline box. This inline box does not get enclosed in another anonymous inline box - it participates directly in its containing block's inline formatting context by way of being laid out on a line box generated within that formatting context. 2) That sounds familiar :P – BoltClock Sep 12 '18 at 05:25
  • 1
    Thanks, Alohci and @BoltClock! Also enjoyed your update Alohci. One of the most confusing parts to me is how the element boxes (content, padding, border, margin) related to the generated principal boxes (i.e. inline boxes, atomic inline-level boxes, block-level boxes, block container boxes (and their union block boxes)). Because, it's not always the case that generated principal boxes matches the height / width of boxes of element that generated them. The inline box is an example: Its size is determined by line-height properties, and thus completely unrelated to element itself. – Magnus Sep 12 '18 at 13:51
1

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>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415