Why is there no unit line height in this example depending on percent or em?

I am puzzled by the behavior of the following CSS, also illustrated in this script .

<style type="text/css"> p { font-size: 14px; } .percentage { line-height: 150%; } .em-and-a-half { line-height: 1.5em; } .decimal { line-height: 1.5; } .smaller { font-size:50%; } .caption { font-weight: bolder; font-size: 80%; } </style> <p class="caption">default line spacing</p> <p>This tutorial provides a brief introduction to the programming <span class="">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p>This tutorial provides a brief introduction to the programming <span class="smaller">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="caption">line-height: 150%</p> <p class="percentage">This tutorial provides a brief introduction to the programming <span class="">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="percentage">This tutorial provides a brief introduction to the programming <span class="smaller">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="caption">line-height: 1.5em</p> <p class="em-and-a-half">This tutorial provides a brief introduction to the programming <span class="">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="em-and-a-half">This tutorial provides a brief introduction to the programming <span class="smaller">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="caption">line-height: 1.5</p> <p class="decimal">This tutorial provides a brief introduction to the programming <span class="">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> <p class="decimal">This tutorial provides a brief introduction to the programming <span class="smaller">language</span> by using one of its picture-drawing libraries. This tutorial provides a brief introduction to the programming language. This tutorial provides a brief introduction to the programming language.</p> 

The first two paragraphs have line spacing by default. In the second paragraph there is one word that is less. But this does not affect the line spacing in this paragraph. Not that it was, but then -

The following two paragraphs have line-height: 150% . Again, the second paragraph has one word that is smaller. But this time, for unknown reasons, a smaller font creates extra space between the first two lines (at least in Safari, Chrome, Firefox and Explorer). This is the original problem in my CSS that I was trying to fix. (I assume this has something to do with the fact that the browser compresses the word and then shifts it down vertically to rebuild the baselines.)

The following two paragraphs have line-height: 1.5em . I understand that 1.5em same as 150% . Indeed, the behavior is the same: extra space between the first two paragraphs of the second paragraph.

But here, where it gets weird : the next two paragraphs have line-height: 1.5 - not a single unit is specified. This time the problem with the extra space disappears.

6bJu2.png

In general, CSS seems to give consistent line-spacing results when the row heights of the parent and child are different (through inheritance of an undivided value), but inconsistent results when the row heights of the parent and child are the same.

So my questions are:

  • I know there the intentional semantic difference in the CSS specification between 1.5 and 150% or its synonym 1.5em . (Namely, a single value is passed to the child, and its row height is calculated using the size of the child font, while a percentage value or em value will calculate the row height for the parent, and then the calculated value is passed to the child.) But how does this explain the difference in the behavior observed here? Where does the extra space come from? If this is a consequence of some CSS positioning rule, then what is this rule?

  • Or, if these examples should display the same way, which one is not executing correctly? (Note on Q2: the fact that quirk renderings work the same in different browsers strongly indicates that none of them are implemented correctly, which will return you to question (1).)

  • In practical terms, is there a drawback in switching to dimensionless dimensions like 1.5 for line-height ? (Answer: no)

+47
html css css3
Dec 20 '13 at 2:29
source share
4 answers

Based on the hints in the suggested answers, I think the rendering behavior discussed in these examples is inconsistent, but true and due to the interaction of several rules in the specification and the general CSS box model .

  • CSS computes the lead L needed for the box using the line-height = L + AD formula, where AD is the "distance from top to bottom" of the font. Then “half the leader is added above A and the other half below D.” So a text that has font-size:16px and line-height:24px will have 4px leading above and below. Text that font-size:8px and line-height:24px will have 8px leading above and below.

  • By default, however, "the user agent must align the glyphs ... with their respective initial conditions." . It begins to explain what is happening here. When the line-height specified in percent or em, the computed value is inherited (here, smaller span). Meaning, the smaller range is the same line-height as the parent block. But due to L + AD, the text of this interval has more leadership at the top and bottom, and thus the baseline is higher in its field. The browser pushes down the smaller scale vertically to fit the baseline.

  • But then the browser had a new problem - how to deal with the interval line in the closing block, which was violated by this process of adjusting the baseline. The specification also allows this: the line-height of a level block element "indicates the minimum height of the lines within the element . " Meaning, CSS makes no promises that you will get line-height , you just get at least that amount. So the browser pushes the lines in the closing block so that the Implemented child box matches.

The reason this contradicts is because it is the opposite of how most word processors and page layout programs work. In these programs, a smaller piece of text within a paragraph is aligned with its baseline (for example, CSS), but the line height is used as the distance between the baselines, and not as the field surrounding the smaller text. But this is not a mistake - CSS is designed around the box model . Therefore, in the end, we could say that this interval behavior is a consequence of this model.

This still leaves us with an explanation of the behavior in the example with dimensionless row height:

  • First, note that when line-height not specified, the default browser will use dimensionless line height. This is the required specification : the initial value of line-height is normal , which is defined as having “the same value as“ number> ”, and the specification recommends the value“ between 1.0 and 1.2. ”And this is consistent with what we see in the above above examples where paragraphs with line-height: 1.5 have the same behavior as paragraphs without setting the line height (i.e. they imply getting line-height: normal )

  • As others pointed out, when in a line-height: 1.5 paragraph, the estimated line height of the paragraph is not inherited from the smaller range. Rather, the smaller range calculates its own line height based on its own font size. When a paragraph has line-height: 1.5; font-size: 14px line-height: 1.5; font-size: 14px , then its estimated line height is 14px * 1.5 = 21px. And if the smaller span has the font-size: 50% property, then its font size is 14px * 50% = 7px, and its line height is 7px * 1.5 = 10.5px (which is usually rounded to a whole pixel). But overall, smaller is half the size of the surrounding text.

  • As before, the browser will vertically align the smaller range to an adjacent baseline. But this time, because the box around smaller shorter than the surrounding text, this overhaul has no side effects in the closing block. This is already suitable, so there is no need to distribute the lines of the parent paragraph, as it was before.

Both cases represent a consistent implementation of the specification. . This is good news because it means that we can predict line spacing behavior.

This brings us back to the original reason for this question. Although I now understand that the CSS block model requires behaviors like a practicing typographer, this is the rare behavior I want. I want the lines inside the paragraph to have a consistent and accurate line spacing, even if some text spacing inside this paragraph is smaller.

Unfortunately, there seems to be no way to directly establish the exact spacing between lines in CSS, as you can do in a text editor or page layout program. Again, this is due to the CSS block model: it does not use the linear spacing model of the baseline to the baseline, and line-height is defined as the minimum dimension, not the maximum.

But we can at least say that unit line heights give the best approximation of the exact line spacing in CSS. Fussy typographers such as myself should feel comfortable using them because dimensionless values ​​are approved by the specification and they give consistent results in browsers. They are not hacked and not outdated.

The danger is that they are still only approaching. Single line height values ​​do not change the basic CSS field model and CSS field layout rules. Thus, it is possible that in some cases the edges will not have the expected result. But eternal vigilance is the price of a good print shop. Be careful.

+26
Dec 28 '13 at 19:01
source share
— -

EDIT

I created a codepen to demonstrate a lead created using different values . Hope this gives a better explanation.




I can answer your questions, but only theorize (at the moment) about the extra distance that you see (and provide potential work).

Your questions

Is there an intentional semantic difference in CSS between 1.5 and 150%, which explains the difference in behavior?

Yes, actually!

A numerical coefficient (1.5 in this case) is inherited and used to calculate the line height of each descendant relative to its font size.

A percentage (150%) is used to calculate the line height based on the font size of the parent element. The resulting, pre-computed value is then inherited by its descendants.

Or, if they should be the same, then which one is doing wrong?

They are intentionally different. (See W3C Specification )

From a practical point of view, is there a drawback in switching to raw decimal numbers, such as 1.5 for line height?

This is usually the advantage of using decimal values, because the legacy line-height will adapt better. But there are times when it does not suit your needs.




Extra interval problem

I noticed that if I set vertical-align to your small text on middle or bottom , there won't be a problem. But this is not a good solution.

I guess this is because the smaller text uses the inherited computed line-height combined with the line layout. Since the text is smaller and sits lower, but has the same line height as the surrounding line, the lower half leads actually down, and the upper half will not reach as high as the surrounding text.

So, let's say the base font size is 16 pixels, and the line height is 24 pixels. The presenter will be 4px on both sides ((24-16) / 2). When the font size is 50%, it is 8 pixels, but the line height remains 24px. Thus, the lead becomes 8px on both sides ((24-8) / 2).

The source texts are aligned, therefore, ceteris paribus, the smaller text will expand 4 pixels below normal text. But since the text (and its corresponding content area) is smaller, the lower half goes further backward, so you only see a pixel or two changes, and only at certain percentages (getting more as you become smaller - try to exit)

I really need to use images for this, but I can't now ... maybe I can add a bit later.

I don’t know if this helps at all, but I definitely better understand how line-height works in general now!

References: http://www.w3.org/wiki/CSS/Properties/line-height http://meyerweb.com/eric/thoughts/2006/02/08/unitless-line-heights/ http: // www .maxdesign.com.au / articles / css-line-height /

+5
Dec 27 '13 at 20:42
source share

It seems like a simple answer to your question: inheritance . line-height: 150% and line-height: 1.5em in your example inherits the value of the computer of its parent, while the numerical value is not equal.

In your example, the parent <p> has a row height of 21px, if you use percent or ems to indicate the row height of your nested <span class="small"> element, it will be calculated based on the inherited computed value of 21px; 21 * 1.5 = 31.5, but if you use a numeric value for the line height, it will be calculated based on the actual font size; (14 * 0.5) * 1.5 = 10.5.

You have a great answer to your question here .

0
Dec 23 '13 at 21:28
source share

Matthew, try adding "line-height: 1.5em;" to the ".smaller" class. Does it solve the problem for all ads?

I think this will happen, and if so, then this should be a matter of inheritance. The difference between 1.5em / 150% and 1.5 (without any unit) is that the first two calculate the value and set it in absolute value to its element, so the child of this element without its own declaration of the height string inherits the calculated value, not a percentage.

Declaring a row height without a unit, however, has a different result for this child, because what is actually inherited is a number (1.5 - in your case), which will again be calculated on the child as a result of the value, related to his own font size, not his parents.

You say that the specification defines the whole version in the same way, and therefore the results should be the same, but here is what is actually said:

 <number> 

The property value used is a number times the font size of the element. Negative values ​​are illegal. The calculated value matches the specified value .

 <percentage> 

The calculated property value is the percentage times the size of the calculated element size . Negative values ​​are illegal.

That is the difference: what is actually calculated. When you declare a string as a percentage (or using ems), the computed value is the quoted numerica value, whereas in the case of a dimensionless declaration, the computed value matches the declared value, which allows the child to be compromised.

In the meantime, I did a test, and I think I was right.

When you declare the row height in percent (or using ems), the computed value is inherited by the span element. Thus, the span element line height will be 24px instead of 13.5px. But, since the font size of the span element is actually smaller, the result below will be larger than its parent. (24px-9px) /2=7.5px. This way you will get 7.5px lower and not (24-16) / 2 (4px). As a result, you get an additional 7.5px-4px (3.5px).

0
Dec 28 '13 at 8:47
source share