Based on clues in the proposed answers, I think the rendering behavior seen in these examples is counterintuitive, but correct, and mandated by the interaction of several rules in the spec, and the overall CSS box model.
CSS calculates the leading L needed for a box by the formula
line-height
= L + AD, where AD is "the distance from the top to
the
bottom"
of the font. Then "half the leading is added above A and the other
half below D." So text that has font-size:16px
and
line-height:24px
will have 4px of leading above and below. Text
that font-size:8px
and line-height:24px
will have 8px of leading
above and below.
By default, however, "user agent must align the glyphs ... by their
relevant
baselines.".
This starts to explain what's happening here. When line-height
is
specified by percentage or em, a computed value is inherited by the
child (here, the smaller
span). Meaning, the smaller
span gets
the same line-height
as the parent block. But because of the L +
AD formula, the text of that span has more leading on the top and
bottom, and thus the baseline sits higher in its box. The browser
pushes down the smaller
span vertically to match the baselines.
But then the browser has a new problem?— how to deal with the line
spacing in the enclosing block, which has been disrupted by this
baseline-adjusting process. The spec resolves this too: the
line-height
of a block-level element "specifies the minimal
height of line boxes within the
element".
Meaning, CSS makes no promise that you'll get your exact
line-height
, just that you'll get at least that amount. So the
browser pushes the lines apart in the enclosing block so that the
realigned child box will fit.
The reason this is counterinitutive is that it's the opposite of how most word processors and page-layout programs work. In these programs, a smaller stretch of text within a paragraph is aligned by its baseline (like CSS) but line height is enforced as a distance between baselines, not as a box surrounding the smaller text. But that's not a bug —?CSS is designed around a box model. So in the end, we could say that this spacing behavior is a consequence of that model.
That still leaves us to explain the behavior in the example with the unitless line-height:
First, note that when no line-height
is specified, the browser
will apply a unitless line-height by default. This is required by
the
spec:
the initial value of line-height
is normal
, which is defined to
have "the same meaning as <number>", and the spec recommends a
value "between 1.0 and 1.2". And that's consistent with what we see
in the examples above, where the paragraphs with line-height: 1.5
have the same behavior as the paragraphs with no line-height setting
(i.e., they are impliedly getting line-height: normal
)
As others have pointed out, when the paragraph has
line-height: 1.5
, the calculated line-height of the paragraph is
not inherited by the smaller
span. Rather, the smaller
span
calculates its own line height based on its own font size. When the
paragraph has line-height: 1.5; font-size: 14px
, then its
calculated line height is 14px * 1.5 = 21px. And if the smaller
span only has the property font-size: 50%
, then its font size is
14px * 50% = 7px, and its line height is 7px * 1.5 = 10.5px (which
will generally be rounded to a whole pixel). But overall, the
smaller
box is half the size of the surrounding text.
As before, the browser will vertically align the smaller
span to
the adjacent baseline. But this time, because the box around
smaller
is shorter than the surrounding text, this realignment
doesn't have any side effects in the enclosing block. It already
fits, so there's no need to spread the lines of the parent paragraph, as
there was before.
Both cases represent a consistent implementation of the spec. That's good news, because it means we can predict the line-spacing behavior.
That brings us back to the original reason for this question. While I now understand that the CSS box model requires this behavior, as a practicing typographer, this is rarely the behavior I want. What I want is for the lines within a paragraph to have consistent & exact line spacing, even if some spans of text within that paragraph are smaller.
Unfortunately, it seems there's no way to directly enforce exact line spacing in CSS as one can in a word processor or page-layout program. Again, this is because of the CSS box model: it doesn't use a baseline-to-baseline line-spacing model, and line-height
is specified to be a minimum measurement, not maximum.
But we can at least say that unitless line-height values produce the best approximation of exact line spacing in CSS. Fussy typographers like myself should feel comfortable using them, because unitless values are endorsed by the spec, and they produce consistent results across browsers. They are not a hack, nor are they deprecated.
The caveat is that they're still only an approximation. Unitless line-height values don't change the underlying CSS box model, nor the CSS box-positioning rules. So it's possible that in some edge cases, they won't have the intended result. But eternal vigilance is the price of good typography. Be careful out there.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…