Skip to content

[css2][css-inline] Definition of line-height calculations contradicts itself #391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
fantasai opened this issue Aug 8, 2016 · 7 comments

Comments

@fantasai
Copy link
Collaborator

fantasai commented Aug 8, 2016

I'm having a little trouble with the CSS2.1 spec.
https://drafts.csswg.org/css2/visudet.html#line-height

for each glyph, determine the A and D. Note that glyphs in a single element may come from different fonts and thus need not all have the same A and D. [...]

Still for each glyph, determine the leading L to add, where L = 'line-height' - AD. Half the leading is added above A and the other half below D, giving the glyph and its leading a total height above the baseline of A' = A + L/2 and a total depth of D' = D + L/2.

So, let's suppose the line-height is 1. The leading is zero, right? So we end up with some glyphs with ascenders A1, A2, etc. and descenders D1, D2, etc. The As are not all identical. Neither are the Ds. When we align them all along the baseline, we get a set of boxes that are 1em tall, but are slightly shifted up and down.

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

If we draw the bounding box of the boxes described above, the height of that bounding box is more than 1em, right?

@frivoal frivoal added the css-inline-3 Current Work label Aug 9, 2016
@kojiishi
Copy link
Contributor

kojiishi commented Aug 9, 2016

If we draw the bounding box of the boxes described above, the height of that bounding box is more than 1em, right?

Yes, according to my understanding of the spec and our code.

@fantasai
Copy link
Collaborator Author

fantasai commented Aug 12, 2016

According to the following test:

<!DOCTYPE html>
<meta charset=utf-8>

<style>
p { border: solid 1px black; color: silver; font-size: 100px; line-height: 1; margin: 0.1em;}
p > * { border: 1px dotted red; }
</style>

<p style="font-family: Ahem, SimSun"><span>Ép不</span>
<p style="font-family: SimSun, Ahem"><span>Ép不</span>
<p style="font-family: Ahem, SimSun"><span>不</span>

Blink and Gecko use the metrics of the first available font to determine the bounding box of any given inline.

Related test with multiple inlines (gives different results than font fallback):

<p style="font-family: SimSun"><span>不A</span><span style="font-family: Ahem">Ép</span>

I think this behavior makes sense and we should update the spec accordingly. It has the benefit of minimizing any line-height
jitter.

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

Afaict this would mean fixing the contradiction in favor of the second clause in this sentence, not the first.

@kojiishi
Copy link
Contributor

Afaict this would mean fixing the contradiction in favor of the second clause in this sentence, not the first.

Ah, sorry, I misunderstood this is about line box (item 3 of 10.8) when I replied before.

For inline box, the code looks like it tries to get max of ascent/descent of all used fonts in the inline box, but I didn't stepped through them. Your test indicated only from the first available font? Is the larger ascent of fallback font supposed to be cut?

@litherum
Copy link
Contributor

I think all the browsers agree on how this is handled.

I tested this by making an Ahem font, but didn't including the letter "m". Then, I made a second Ahem font, but this one has a taller ascent/descent, but doesn't include the letter "n". Both fonts include the letter "a". Then, I made a similar test as @fantasai except with this markup:

<p style="font-family: 'MyAhem', 'MyAhemLargeAscent'"><span>amn</span></p>
<p style="font-family: 'MyAhemLargeAscent', 'MyAhem'"><span>mn</span></p>

As you can see in the results below, everyone seems to do the same thing.

Here are the results (The first two lines are just making sure that the correct fonts are used; the relevant lines are the bottom two lines)
macos
macos 2
windows 10 2
windows 10

And here are the original files:
Fallback bounds test.zip

@antonprowse
Copy link

antonprowse commented Oct 11, 2016

Hi fantasai! It's been a long time; hope you're doing great.

I think you've hit upon an issue which we've discussed in detail in the past but which has ended up being edited into the spec in a contradictory way.

From what I gather from conversations in 2010/11 with Bert, the "height" of an non-replaced inline box is intended to be exactly the value of line-height, which means that your proposed fix in favour of the second clause in the spec sentence you quoted is the right way to go.

Your analysis of the A,D stuff is correct, and I think it was an oversight that the possibility of a bounding box of the glyphs+leading being taller than the value of line-height was not spotted by any of us when Bert made a final set of edits to this section of the spec (to kill of a whole bunch of issues that had been raised). I can see how the mistake could have slipped in, because, as so often, there was a complex history to this box height stuff, as I explain below.

Originally the spec was very unclear about the height of an inline box, and we aimed to make it more concrete. Certainly, the height was never and is not the content area height. I described a mental model of the situation using "guide boxes" (rectangles, really) which are exactly line-height high and which are vertically centred within the content area box of the inline box. The distance from the top of the guide box to the top of the content area box (which may be negative) is interpreted as the half-leading - and hence half-leading becomes a property of the inline box rather than of the individual glyphs, although in any case the leading and half-leading is not a relevant concept in CSS; we define it simply because it supposedly makes the model easier to visualize because it's a concept that people are familiar with. When calculating the vertical extents of the line box, we only consider the relative positions of the guide boxes; the content area box (and indeed border box and margin box) of the inline boxes is totally ignored. You rather liked this mental model, I believe, and were intrigued by a rendering example which is very hard to make sense of without guide boxes but which makes total sense with them. See the last two sections of the following e-mails (and ignore the rest of the e-mails!):
https://lists.w3.org/Archives/Public/www-style/2010Jul/0535.html
https://lists.w3.org/Archives/Public/www-style/2010Aug/0012.html

In the spec, we didn't end up explicitly describing the model in terms of "guide boxes", although it has always been the underlying concept and we did end up with it being a bit more transparent (which is why the spec now explicitly talks about inline boxes which are line-height "high" - and again, note that this "height" is not what we usually think of as height, namely content-area height).

But before that happened, some relevant other edits happened, which have lead to the unforeseen contradiction that we're discussing. Firstly, with a view to resolving other editorial issues in 10.8 (of which there were many, and tricky), Bert proposed a change which meant that the inline box could be more than line-height "high", in order to accommodate the fact that it could contain not only glyphs from fonts with different metrics but also other inline boxes from child elements. I was wary about the proposed change, because I felt that it was a change from the existing logic, and I asked for evidence of browser interop for it: https://lists.w3.org/Archives/Public/www-style/2010Oct/0106.html

Indeed, it was a change, and it later transpired that having inline box height dependent upon other inline boxes from child elements would contradict other changes which Bert wanted to make, as I pointed out in https://lists.w3.org/Archives/Public/www-style/2011Mar/0139.html . So (happily, from my perspective) it was decided to go back to having the inline box height "not be dependent on child elements and thus guaranteed to be 'line-height'. We needed that for issue 153, which requires a box of that height for 'vertical-align' to work on" [Bert]. See https://lists.w3.org/Archives/Public/www-style/2011Mar/0635.html . And indeed a box of that height is required (it's the "guide" box, and it's used for determining vertical alignments and line spacing) so the decision was a good one. The problem is that the conclusion - "thus guaranteed to be 'line-height'" - is actually false, as you've hit upon; unfortunately, the earlier observation that the inline box might be taller than line-height due to glyphs from fonts with different metrics was forgotten.

Of course, we want that conclusion to be true! So to fix the issue we need to change the other stuff which currently makes it false. Really we need to be more explicit about the guide box model (and, in particular, move away from the idea of glyph-specific leading).

@astearns astearns removed the Agenda+ label Oct 12, 2016
@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed css2 fixing, and agreed to the following resolutions:

RESOLVED: fix the erroneous conclusion in section 10.8
The full IRC log of that discussion
<astearns> topic: css2 fixing
<fantasai> https://github.com/w3c/csswg-drafts/issues/391
<rachelandrew> suggested resolution is to fix the erroneous conclusion in section 10.8
<fantasai> github topic: https://github.com/w3c/csswg-drafts/issues/391
<rachelandrew> RESOLVED: fix the erroneous conclusion in section 10.8

@fantasai
Copy link
Collaborator Author

@antonprowse So I drafted the idea of guide boxes more-or-less into css-inline-3. :)
Relevant sections are

I think this issue is resolved in css-inline-3. Leaving it open for @gsnedders to handle in CSS2.

@fantasai fantasai removed the css-inline-3 Current Work label Jun 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants