Open frivoal opened 7 years ago
I understand the motivation, but I'm not a big fan of adding more automatic magic behaviors.
line-height: normal
causing different layout by browsers/platforms are already widely known facts. Most recent reset.css has line-height: 1
. Fixing it automatically only when line-height-step
is set looks like we're recommending not to to set line-height
. We're not, correct?
Also, the problem you state isn't limited to line-height
. What if author forgot to set font-size
? If the font-size is larger than a test device, it may result in two units, but we can't fix it, correct?
I have a mid preference to let authors to deal with their errors, and minimize the magic behaviors in the platform.
line-height:normal
being a little different depending on the browser is not a major problem when step sizing is not involved, because the differences are subtle. In this case, the differences could be large (some browsers/os/fonts combinations getting double spaced, some other not), and the fix seems easy.
When the problems are obvious and the solutions hard, leaving things up to authors is fine. Here it's not the case.
If we make behavior dependent on whether or not line-height-step
is initial, the initial value needs to be none
.
If we want font-based line heights to be possible to use with step-sizing, we need to add a normal
keyword (that computes to its absolute length) to line-height step
If we want font-based line heights to be possible to use with step-sizing, we need to add a normal keyword (that computes to its absolute length) to line-height step
Can you clarify how author can do:
line-height: normal;
line-height-step: 18px;
that was what I wanted to ask but probably failed, sorry about that.
If we make behavior dependent on whether or not line-height-step is initial, the initial value needs to be none.
I'm fine to add none
if desired.
Added i18n label because this proposal will cause lines to overlap for some scripts.
Since I wasn't able to express my points very well in the weekly conf call, let me continue my points here by cc'ing people who spoke at the weekly on 25 Jan, from IRC log: @astearns @stevezilles @tantek @tabatkins @dbaron @fantasai @dauwhe @litherum @FremyCompany There were some points what I said didn't seem to be understood correctly, or I didn't understand even by reading IRC log, so appreciate to read through and comment here if any.
line-height: normal
doesn't produce a robust layout as discussed, and I agree that a robust layout is one of important principle in CSS, and that line-height: normal
is against that.
The purpose of line-height: normal
is different; it is designed to avoid line overlaps as much as possible. Making any text readable without unexpected overlaps is also one of important principles in CSS. These two important principles conflict to each other. I think that is why line-height
gives a choice to authors, and I think CSS chose the right default because overlapping is worse problem.
What I was trying to say at the weekly was that we need to give the choice to authors regardless rhythmic sizing is used or not, and IIUC this is also what @litherum was trying to say.
I made a multi-script sample text here (credits to @r12a and @aphillips, thank you!) For scripts in this example, I hope you see normal
works perfectly in all browsers, but if we were to pick one fixed value, probably "1.8" is a good value. But I saw an example where "1.8" wasn't still tall enough before. Pick "2"? But it's too tall for some other scripts, such as Latin.
Or, maybe, I wonder, from @fantasai's comment above, this point was understood but cases where font metrics-based line height and rhythmic sizing used together was not understood?
If that's the case, I'm quite sure this case is common; author wants a constant rhythm, such as 18pt. The page has CGM that text can be in various scripts. Author wants to prioritize "lines not to overlap" over "possible additional space when falls back to bad fonts occurs," because font fallback is more predictable than CGM text content. In this case, the combination of normal
and rhythmic sizing is what the author needs.
If the author uses line-height: normal
, Latin lines will fit to one step unit, while Tibetan may fit to two or three step units, but still the rhythm is kept.
...or maybe concerns discussed there was different from either of above, appreciate if someone can explain more if so.
Talked with @tabatkins offline, he said he might try to come up with a new proposal, so I look forward to seeing it.
He also said it became clearer after we talked, so I guess I didn't do good job in conf call or comments above. Sorry about that, let me try to simplify the points.
line-height: normal
.Happy to discuss more if anyone can come up with new proposals, or disagree with me on 3-5.
Blink is considering shipping line-height-step. Please let us know if there's a specific proposal here for changes which could cause a web compat problem in the future if we were to ship now. If approved, line-height-step support could make it to Chrome stable as early as June, so we'd still have a few months to safely make breaking changes or pull the feature if consensus can be reached.
Alright, I think I have a solution that lets line-height:normal
fulfill its purpose and solves the double spacing problem we've been discussing.
Hypothesis:
line-height:normal
needs to be left alone, for the reasons Koji saidline-heigh-step
, you (almost?) never want to set it to something smaller than the line height of the element that establishes the rhythm.line-height-step
, you do want it to be able to be smaller than the line height of the element it is inheriting into. That is what enables things like titles to be enlarged to a multiple of the step size.Proposal:
line-height-step: none | [ <length> [ safe | unsafe ]? ]
none
computes to (or behaves as, I don't care) 0 unsafe
safe
and unsafe
are omitted, it is the same as safe
<length> unsafe
does the same as what the spec says now<length> safe
computes to max( 1lh, <length>)
unsafe. Nb: lh
resolves at computed value time to an absolute lenght, so the computed value of line-height-step
, and therefore what we will inherit, will be an absolute length.Let's walk through that:
<article>
<h1>Title!</h1>
Lorem Ipsum…
</article>
article {
font-size: 16px;
line-height: normal;
line-height-step: 20px;
}
h1 { font-size: 1.5em; }
First, assume a font for which line-height: normal
gives 1.2:
20px safe
⇒ 19.2px < 20px ⇒ 20px unsafe
20px unsafe
⇒ Same as now
Now, let's assume a font for which line-height: normal
gives 1.3
20px safe
⇒ 20.8px > 20px ⇒ 20.8px unsafe
20.8px unsafe
⇒ The step size is a little larger than expected, allowing the rhythm to work without creating blank lines everywhere
I don't understand what this means:
safe computes to max( 1lh, ) unsafe. Nb: lh resolves at computed value time to an absolute lenght, so the computed value of line-height-step, and therefore what we will inherit, will be an absolute length.
What is the computed value of max(1lh)
when line-height: normal
? I tried to learn what the lh
spec says, but I can't read from it.
Could you write down in more plain English?
BTW, a discussion at mozilla.dev.platform clarified that the use cases (and thus desired behaviors) are different between mine and Latin. This has been gradually understood, if I think now, but I was unconscious. The discussion was so much helpful to clarify that.
So I added a section about East Asian Casual Vertical Rhythm to clarify different two (or three, not sure at this point) use cases, and which property and combination works good for which use cases.
I'm under impression that even for the strict vertical rhythm, Latin and East Asia are different enough that we're likely to end up with 3 different behaviors; 1) East Asian Casual, 2) East Asian Strict, and 3) Latin Strict, but maybe we can merge 2 and 3, or other writing systems have 4th or more use cases. That should be figured out sometime in future, but as I wrote there, I'm focusing on East Asian Casual first.
What is the computed value of max(1lh) when line-height: normal? I tried to learn what the lh spec says, but I can't read from it.
Could you write down in more plain English?
line-height:normal
behaves the same as if a number was specified, except the author doesn't know what that number is, since it depends on the font (and on how the browser chooses to deal with it).
But once the browsers knows the font and the font size, it can know how many pixels tall a line is going to be when line-height is normal. That's 1lh
. Of course the actual line might end up being taller if you change font size on inlines, or have inline images, or superscripts... But assuming a line with nothing special in it, you know how tall it would be.
So, if you have specify 20px safe
, either:
I think that should cover 99% of the use cases (which is why I made "safe" the default), and if you actually want the unsafe
behavior, you can ask for it.
I believe line-height: normal
is allowed to do things that are a function of the font -- which means it can be a function of font selection and the actual text that is in the element. (I'm not sure if any UAs treat it as a function of the text, or if they just use the first available font. There was definitely discussion in the WG that it ought to consider all fonts used in the text.)
If it's a length unit, it needs a definition of 'normal' that doesn't depend on text.
I'm going after the CSS2.1 definition, which although phrased somewhat vaguely, does not seem to allow (by my reading) considering the actual content of the element:
normal Tells user agents to set the used value to a "reasonable" value based on the font of the element. The value has the same meaning as
. We recommend a used value for 'normal' between 1.0 to 1.2.
I'm sure we can find some wiggle room in that phrasing, but regardless, I would indeed favor a definition of 'normal' that doesn't depend on text. The alternative is just going to make everything more complicated.
@frivoal, I'm so disappointed at my English skill, I still can't understand what the proposal is after tens of minutes of try. Could you try plainer English, or meta-code if possible?
When you said:
that 20px is taller than what this natural line height would be, in which case, everything behaves exactly the same as you specified
I interpreted:
so this means, in meta-code:
if (computed-line-height-step > line-height-from-layout-result) {
if (specified-line-height is not "normal")
use specified-line-height;
else
use ???
}
This logic doesn't make sense, so I'm probably lost somewhere, but don't know what it is.
See 10.6.1 Inline, non-replaced elements
If more than one font is used (this could happen when glyphs are found in different fonts), the height of the content area is not defined by this specification. However, we suggest that the height is chosen such that the content area is just high enough for either (1) the em-boxes, or (2) the maximum ascenders and descenders, of all the fonts in the element. Note that this may be larger than any of the font sizes involved, depending on the baseline alignment of the fonts.
If UA chose to do (2), "all the fonts in the element" depends on text, and that's all 4 browsers do today when line-height: normal
, as @dbaron pointed out.
The CSS Working Group just discussed Avoiding accidental double spacing.
So here's an idea for avoiding accidental double-spacing, although it doesn't quite work (see below), but i figured it was worth noting down anyway:
line-height-step: <length>
property that is inherited, have something like line-height-step: <number> | auto | none
which is not inherited, but that controls a step size (which is conceptually either none
or a length) that is propagated from ancestors to descendants:
auto
, which means the lines of this element use the same step size as the (containing block? / parent?), if anynone
value means the lines of this element do not use a step size<number>
value means this element's step size (a length) is computed based on the element's properties. Values smaller than 1.0 are invalid (or changed to 1.0). The step size is computed by computing the height a line box would have if it contained glyphs from all fonts in the font-family
list (given the other font properties), i.e., using the ascent and descent of each, and the line-height
(which might be normal and thus lead to using external leading), and then multiplying that result by the <number>
value.(I'm not particularly happy with the names I've chosen here.)
So the problem with this as that it doesn't actually solve the font fallback problem, since font fallback often fails to find a glyph in the font-family
and has to fall back to searching for other available fonts.
So on further consideration, maybe font fallback isn't as much of a problem as I thought.
In particular, line-height-step isn't actually aligning baselines to even spacing; it's aligning the line boxes. Font fallback can cause the position of the baseline to vary within the line box, but maybe that just leads to slight baseline jitter rather than accidental double spacing. Maybe that's not so bad. (Although it's not great that it would defer having a solution for real baseline snapping.)
Then I think the remaining question is that we don't actually know what line-height: normal
means (#1254), and which fonts' metrics it considers. If all of the font metrics that could ever be considered for line-height: normal
are considered when evaluating the step length from line-height-step: <number>
as I propose above, then I think things would be ok.
I believe I understand how your proposal work. But I will need to think about it for a while to figure out if:
I'd also note that in our discussion in the meeting yesterday morning, we misinterpreted what CSS2 says about how line-height
works. It does add the half-leading separately per-glyph, rather than computing the half-leading based on the line-height
and the already-unioned content-box bounds. In particular, §10.8.1 Leading and half-leading says:
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. The height of the inline box encloses all glyphs and their half-leading on each side and is thus exactly 'line-height'. Boxes of child elements do not influence this height.
I think this means font fallback remains a problem, i.e., I retract my retraction in https://github.com/w3c/csswg-drafts/issues/938#issuecomment-295747854.
Apologies in advance I'm slow to understand. I hope I understand correctly with the help from @frivoal (he corrected my one misunderstanding, thx.)
I really wish the proposal solves the concern, a few questions for clarification:
font-family
of the element, but does not include fonts from system fallback, correct?font-family
, it can round up, though @frivoal and I wonder whether we'd want to call it "accidental" or "appropriate" is gray. Do you think such case appropriate?Also note, I guess this is already clear to all of us but @fantasai and I tested a bit more last night that, when line-height
is not normal
, line height is consistent across fonts/platform/browser. Test here. normal
is the only case it is not, for a good reason as stated above.
@fantasai had some idea, but need to bake a little more.
Even if line-height
is consistent between browsers -- are the lines actually all spaced at the specified number? If so, then that means that either:
are the lines actually all spaced at the specified number?
Yes, we checked the box size in Inspector, divided by the number of lines and by the value of line-height
, got the font size.
As far as I read CSS2, number is "multiplied by the element's font size" while normal
is "based on the font of the element", so when I was reading Blink code, when number, the height affected only by font size, while when normal
, affected by font metrics made sense to me. Do you see any errors?
Oh, wait, I see what missed...
are the lines actually all spaced at the specified number?
To answer to your question with correct understanding, exact positioning of baselines is not part of the goal for Level 1 of the line-height-step
, because:
dominant-baseline
is implemented. As some claimed, this level of the property is unlikely to be much useful for Latin.When we've got enough infrastructure defined in CSS inline level 3 or in future levels, we can add features to solve baseline jitter problem.
From @dbaron's comment on Apr 21st, I think the baseline jitters is a problem we should look into in CSS Inline L3, so I'm opening a separate issue.
I'd like to propose that line-height-step
is effective only when line-height
is not normal
. The motivation is to respond to the feedback 1 below.
line-height
is normal
. Discussions so far has discovered that when line-height
is not normal
, the used line height is interoperably consistent across browsers/platforms/fonts.line-height: normal
is designed to make used line height dependent on fonts, we can come up with a heuristics to mitigate but can never solve the problem 1.line-height-step
to line-height: normal
, we could add a keyword, like the one in @frivoal's proposal.The problem 1 above applies only when
line-height
isnormal
. Discussions so far has discovered that whenline-height
is notnormal
, the used line height is interoperably consistent across browsers/platforms/fonts.
Really? It doesn't seem to me so. IIRC, there is still inconsistency among browsers when there are inline boxes and font fallback involve.
Oh, I was probably wrong. The used line height should be consistent when the computed value is not normal
.
I don't think we should try to make progress on this issue until https://github.com/w3c/csswg-drafts/issues/1254 & https://github.com/w3c/csswg-drafts/issues/1314 are resolved.
Some general questions: Is CSS-Rhythm intended mainly for CJK text? And, if so, is font fallback a problem in CJK? (It may be the case that most fonts' characters lie within the same-sized em box)
Some general questions: Is CSS-Rhythm intended mainly for CJK text?
I think it is useful for CJK and we should make sure it works well there as well, but it is by no means exclusive to CJK, and should work any language/script.
The CSS Working Group just discussed Avoiding accidental double spacing
.
Some general questions: Is CSS-Rhythm intended mainly for CJK text?
This is designed for CJK use case, and I heard several people saying Latin feels this is not useful, so we removed the Latin feature in January.
I don't have good info how other scripts than Latin/CJK would like it. As far as I tried to ping at i18n WG, I didn't hear back any, and word processors have similar features enabled only for CJK versions. From these, my assumption atm is this is CJK-only feature, but hard to deny scripts that we have not reached yet.
And, if so, is font fallback a problem in CJK? (It may be the case that most fonts' characters lie within the same-sized em box)
I don't have data how common it is, but it's not rare to have Latin font as primary:
font-family: Times, win-cjk-font, mac-cjk-font, serif;
font-size: 12px;
line-height: 1.8;
I think the primary case for CJK is about having consistent height across different font metrics (such as platform/version/user installed fonts differences), but fallback is also a case to cover.
Re-read the IRC log, appreciate your confirmation: @frivoal @dbaron
Do you find where I misunderstood? Since we were talking about test fonts, is it just 5 was not shared, or we want more through tests than 5, or something else?
Some comments in IRC log:
Florian_: I can't figure out which browser is what color.
This test is meant to run in each browser and compare pixels. Sorry that explanation was missing.
dbaron> Does this testcase have font metrics that would trigger the issues we discussed?
It has Latin and tall scripts without font-family
in a line. So it's not cascading fallback, but has system fallback.
dbaron: I think what we agreed only produces it if there's a single element. It doesn't work with multiple when some have font-fallback.
I guess I missed this was on topic, sorry about that. The spec defines line box height to be computed from inline boxes, so I'm not sure how multiple elements can differ. Is this about we don't have tests for this specific case, or do you know somewhere in the spec mention differences in multiple elements?
My assumption -- not really confirmed though -- was that CSS2 already has tests for multiple elements with different size/vertical align/baseline etc., and that if single element with fallback works as expected, multiple elements with fallback is covered by running both tests.
Can I understand your comment that you think a combination test is vital, or do I still misunderstand something?
A couple of more notes:
dbaron> Does this testcase have font metrics that would trigger the issues we discussed?
It has Latin and tall scripts without font-family in a line. So it's not cascading fallback, but has system fallback.
In case whether these system fonts have different metrics or not is still a question, lines with line-height: normal
having different height is a proof of such system fallback fonts having different metrics.
Florian_: I can't figure out which browser is what color.
This test is meant to run in each browser and compare pixels. Sorry that explanation was missing.
I made a ref test from the test above.
I just created three fonts to test what the different browsers do.
tl;dr: All browsers agree about how line-height works (both the magical normal
as well as <number>
).
The test fonts are Ahem, Ahem with a super large ascent, and Ahem with a super large descent. I also selectively removed support for specific characters from each font such that every fallback situation could be tested.
"X" means "present in font"
"_" means "not present in font"
A B C D E F G H
————————————————
AhemSparse | X _ X X _ X _ _
AhemTall | X _ X _ X _ X _
AhemDeep | X _ _ X X _ _ X
The HTML file has a few tests which set line-height normal and line-height font-family: AhemSparse, AhemTall
and font-family: AhemTall, AhemDeep
. All browsers agree on the rendering of all of these tests.
Therefore, we can say:
line-height: normal
means: "For every line inependently: Union all the ascents. Then union all the descents. Add them together. This is your line-height for that specific line. Place the baseline at a distance down equal to the union of the ascents."
line-height: <number>
means: "Ignore secondary fonts. Consider the primary font's ascent and its descent. Add these together, and subtract that from the computed value of line-height. This is the extra vertical space required. Place the baseline at a distance down of half this extra vertical space plus the ascent of the font. Now that you have the baseline position, place the rest of the glyphs on that same baseline."
EDITED: I'm not actually sure my previous analysis is correct. Give me some more time to investigate.
Thank you @litherum this is a great progress.
As I understood the F2F diagram, Gecko (the red) unions all font metrics, but takes center of the union to match to A+D of the first font, so the baseline position maybe different. If you see different baseline positions, it is #1314.
I look forward to further analysis.
I think I understand now why @dbaron was talking about baseline positions in this context; sorry for slow to understand.
If baseline position is different, and if multiple inline boxes are in a line, and if they are aligned at the baseline, there's a possibility to result in different line box height. Is this the concern, @dbaron?
With the @litherum's fonts, I think we can test it by:
<div id="target" style="font-size: 10px; line-height: 1; font-family: AhemSparse, AhemTall, AhemDeep">
<span>AE</span><span>AH</span>
</div>
and Gecko/Edge/Blink/WebKit all computed to 10px.
@litherum @kojiishi I made a similar test, using fonts from google fonts rather than specially crafted version of ahem. The idea is the same though: one has a tall ascent (and short descent), and the other is the other way around. I am testing a few more combinations, and also using multiple ways to visualize & measure the results.
Note that I am only testing what happens with a single element on the line, although I am using fallback fonts. Multiple elements on the line is a separate discussion.
TL;DR: There are more differences than you found with your earlier test. For line height calculations with line-height other than normal, everybody does the same. For line height calculations with line-height:normal, Chrome uses a different logic than everyone else (in some cases). For the position of the baseline within a line-height other than normal, Chrome uses a different logic than everyone else. For which font metrics to use, Firefox uses different data than everyone else (in some cases). For height of content box, there are 3 behaviors: Safari/Edge, Chrome, Firefox. Only in Firefox, the outline of a block may be larger than the block when line-height is not normal.
Here's the test: http://jsbin.com/dacokez
In it, I am testing 4 dimensions that relate to line height:
I've run this in Safari, Firefox, Chrome and Edge.
Conclusions:
Safari and Edge (this is not a typo, I do not mean Safari and Chrome) behave identically in all observable aspects of this test (except font rasterization / hinting / anti-aliasing, but that's out of scope). Chrome is different on a number of things, and Firefox is differentl on different things.
In all browsers, measuring the height of the line box by line stacking of by the border on the div gives internally consistent results. (thankfully. I'd have gone nuts otherwise).
When line-height
is a number or length:
When line-height
is normal
:
Browsers disagree about the height of the content box (background on a span):
line-height
property at all.line-height
is normal or not, but seems to be the same height for all numeric values of line-height
.line-height
property, but it does depend on some metric of the primary font (regardless of whether it is used), it is however a different metric than the one used by Safari/Edge for at least some fonts (different on Revalia in the example).In all browsers except firefox, the outline also gives consistent results and lets us to measure the height of the line box. In Firefox, it takes into account some font-based measurement, and is often larger. It is sized based on all the fonts used, plus the primary font even if it was not used.
Agenda+ F2F, now that we have more details over how various browsers handle line height calculations and related calculations, to see if we can try to converge on that.
Thank you @frivoal for the investigations.
In Paris, I'd like to take a step back and ask opinions from more people, especially, from who haven't spoken much yet.
Here's my understanding of the history.
line-height: normal
does font-dependent layout, and this issue was re-defined as "font-dependent layout and vertical rhythms should not work together".Since then, IIUC, in Tokyo and in comments above, we're trying to understand what "font-dependent layout" is in CSS, and try to find a way to disable either it or vertical rhythms when the other was enabled. @frivoal's detailed investigation above should help this discussion greatly.
Assuming my understanding so far is correct, I think we're missing a few pieces before diving into solutions.
In Tokyo, I was supportive to disable either one. But as I thought about its side effects and i18n impacts, I'm not sure if this is the right way to go, and I would like to hear opinions from more people.
So I'd like to ask, in Paris:
@dbaron, @FremyCompany, @litherum, could you mind to consider above? I can explain my position too (guess it's obvious but in case ;-) and with all opinions, I'd like to review our position to all vertical rhythm features.
I also hope @fantasai, @frivoal, @astearns, @dauwhe, and all other text people can share thoughts in Paris. I hope you don't mind I listed only implementers above, I just listed missing information atm from what I can understand.
@kojiishi
I think I disagree with one point of what you said above:
Then we learned that line-height: normal does font-dependent layout, and this issue was re-defined as "font-dependent layout and vertical rhythms should not work together".
At least from my side, the conclusion was not "should not work together", but we should find a way to make sure that font-dependent differences in layout and vertical rhythms should not interfere to create completely different results in different browsers / OS (for example, normal rhythm in one browser, double spacing everywhere in another). One way is to turn off vertical rhythm, another way would be to find a solution that avoid this bad result.
I was initially searching for the solution when we (or just me? maybe other people knew it already) realized that there were spec ambiguities and lack of interop.
With the investigation we've done now, I think we have confirmed that there were differences in the resulting layout, but that implementations were actually quite close. I think the number of things we need to agree on to have actual interop might not be all that bad.
I hope we can first resolve this, and make sure that we have actual interop on line-height calculations. Even if we do not get to full interop on how browser read font metrics (and we will not get interop on which fonts each browser actually uses), I think this will already be a good step forward.
I also think that even though I initially misunderstood how line-height: normal
works, I think a simple variant my proposal to solve the instability problem of line-height:normal
together with vertical rhythm may actually work. But before we discuss that, I want to try and close the line height calculations.
I think I disagree with one point of what you said above:
That's how I understood @dbaron's comment in mozilla.dev.platform, which looks like stronger than yours, but I'm not sure if I understand correctly, so I'd like to hear his comment first.
Also, I'd like to hear who hasn't spoken much yet; specifically other two implementers. After 6 months this issue was created, we haven't even agreed on the problem yet.
Do you mind discussing this first?
@shans and I were discussing this, and Shane thinks he has a suggestion we haven't seen yet, which I think is reasonable.
Basically, line-height: normal
is UA-defined. This is the source of our problem, but it might also be our solution - what if, when line-height: normal
was "slightly larger" (according to some UA-defined threshold) to a multiple of line-height-step
, we adjusted the value of normal
to exactly the value of line-height-step
? That would avoid the accidental double-spacing by default, which is what we want here. If people don't want their line-height
to get adjusted, they just have to set it to an explicit value, which is also just fine.
We think this works intuitively for authors, and automatically handles the issue here. Thoughts?
@tabatkins This is maybe a good solution but, technically speaking, this just shifts the problem.
With this in place, if on Mac OSX the font cause a 13px line-height and line-step is 12px, but 13px is deemed close enough from 12px that you snap, then you don't get double-lining. Let's say that on Windows the font resolution is rounded up instead of rounded down and you get 14px, which is different enough from 12px that you don't snap back, then you double-space every line. If you author on a Mac WYSISYG you might never find out.
Now the question of course becomes whether you shifted the problem enough that it becomes so difficult to repro in practice that it would be considered a gross author mistake. I would be ok with that if the UA-defined threshold can be made big enough that font-variation alone could not explain the double-spacing (such the author must also have grossly miscomputed its line-step if double-spacing becomes possible).
(I think I'd also be also ok if all browsers agreed to cap line-height:normal to the line-step if line-height:<fallback-number>
would not result in double-spacing but the UA's algorithm to compute line-height:normal would. So basically, line-height:normal still applies generally but only if line-height:1.1 and line-height:normal would result in the same amount of line steps being used.)
Thank you @tabatkins, @shans, and @FremyCompany for great ideas! These should help discussion so much!!
I was neglecting to write down, sorry, but I've changed my position since April. In April, I was thinking in similar direction; limit or disable either line-height:normal or line-height-step in some ways, but I'm moving to a different position now.
I think this is an issue that we should not solve. The hardest part of this issue from my point of view is that, this issue is about conflicting requirements. I understand many WG members think, as in @tabatkins's comment above, line-height: normal
is "the source of the problem". On the other hand, line-height: normal
is a feature many other people rely on, or even require. It looks to me that solving either one would sacrifice the other request.
It looks like, as far as I understand (maybe wrong, Florian seemed to understood differently) @dbaron went to opposite direction even stronger, so I'd like to hear the explanation of his opinion to understand it better, and also what other implementers think.
I understand people supporting this issue are keen to interoperable layout. That's one key goal for us, but CSS also has been providing font- and content-dependent layout feature. In this mode, layout results are not pixel-interoperable, but impls interoperably provide readable content regardless of fonts, content, and scripts. This is another key goal for us, and in CSS, both height
and line-height
are font-/content-dependent by default.
I have several reasons to believe solving this issue is net-loss, we can discuss in Paris, but I'm writing down three of them.
First, the issue is when author sets line-height-step
to unreasonable value, and when the author forgot to test multiple browsers/platforms. This is an error case safe guard. It's nice to have, but we already have features, if used inappropriately, would make layout terribly worse only in some browsers/platforms without any safe guards. The safe guard should be in place only if its side effect is reasonably small. In this case, the safe guard will limit other people's requests, and I don't see any good reasons to pick the safe guard and reject the other.
Second. line-height: normal
maybe problematic to some scripts, but more important or required for other scripts. Limiting the combination means we don't provide equal opportunities to all scripts. This maybe ok for line-height-step
, where many WG members confirmed it's not useful for Latin at all and focuses on East Asian use case only, but is more severe for other vertical rhythm features since I wish them to be global features. For any global features, I believe i18n fairness should not be traded off with safe guards.
Third. If we acknowledge this is an issue we must solve, IIUC, it'll hinder most vertical rhythm features. Example:
<style>div { font: 10px/1 serif; }</style>
<div>Bunch of English text, no span, no fallback, to make this simple</div>
Now we apply box-height-step: 5em
to the <div>
. Although we have line-height: 1
, glyph widths vary by fonts/platforms/browsers, so the number of lines varies. It varies even by window width. The result could be 5em height, or doubled to 10em. Is this an accidental jump, or is this an intentional jump? As I understand how people defines accidental in this issue, this is accidental. If author doesn't test other browsers, platforms, or fonts, the layout results differ by double. But again, I think this is intentional.
I can keep writing more, but I hope people gets some basic idea what I'd like to discuss. Hopefully these are from misunderstanding of mine, I'm still having trouble to understand what makes a step/snap accidental, and would like to understand @dbaron's comment better.
First, the issue is when author sets line-height-step to unreasonable value, and when the author forgot to test multiple browsers/platforms. This is an error case safe guard. It's nice to have, but we already have features, if used inappropriately, would make layout terribly worse only in some browsers/platforms without any safe guards. The safe guard should be in place only if its side effect is reasonably small. In this case, the safe guard will limit other people's requests, and I don't see any good reasons to pick the safe guard and reject the other.
I disagree extremely strongly with this. This is an "error case", but a very reasonable one that's pretty easy to fall into. It's not the author doing something unreasonable, it's the author not happening to test on whatever browsers have a slightly-larger-than-normal line-height: normal
value. Since this value has never been problematic in the past, and in general has only a tiny visual effect, it's extremely surprising that they suddenly get a large visual difference when they start using line-height-step
.
That's been the entire point this entire time. A nearly-invisible difference suddenly gets accidentally magnified into a very visible difference.
Second. line-height: normal maybe problematic to some scripts, but more important or required for other scripts. Limiting the combination means we don't provide equal opportunities to all scripts. This maybe ok for line-height-step, where many WG members confirmed it's not useful for Latin at all and focuses on East Asian use case only, but is more severe for other vertical rhythm features since I wish them to be global features. For any global features, I believe i18n fairness should not be traded off with safe guards.
This doesn't make sense to me. If the author is setting line-height-step: X
and it gives single-spacing in their current browser, then that line-height is fine for the scripts in use. What scenario are you imagining where it's necessary for i18n for a script to render larger than the line-height-step in some browsers but not others?
The result could be 5em height, or doubled to 10em. Is this an accidental jump, or is this an intentional jump? As I understand how people defines accidental in this issue, this is accidental. If author doesn't test other browsers, platforms, or fonts, the layout results differ by double. But again, I think this is intentional.
Yes, line-breaking is definitely something authors are already reasonably familiar with; they know it's pretty uncertain. We still see a lot of authors incorrectly assuming something will break to exactly X lines, but it's at least a pretty general knowledge, and it's obvious what's happening when they look at it.
This is totally different from the situation we're worried about, where authors are not generally aware that line-height: normal
varies between browsers and even in different situations on the same browser, and when it does cause double-spacing problems, it's not obvious why it's happening (because the line-height difference is probably only 1px or so, which is very difficult to see). Even a side-by-side comparison will be difficult, since the double-spacing will cause larger layout differences that'll obscure the tiny difference in line heights.
Further, a block-step getting tripped over the line affects that one block; much of the time, it'll mean that instead of the block being 10 steps tall, it'll be 11 or something; that's a relatively insignificant difference in most layouts. This line-height problem, on the other hand, doubles the height of every line, which'll double the height of text-containing elements; that's taking it from 10 steps to 20 steps. The only time the block-step is comparable is if you have a whole lot of blocks that are all expected to be one step tall, and they get doubled in some circumstances; I think you'll agree that'll be relatively rare.
There's really no comparison here. line-height: normal
is a nearly-invisible menace that will bite a lot of authors who are just trying to use line-height-step
in a reasonable, correct way, and screw up their page layout significantly. It's not comparable to box-height-step, and it's not reasonable to push it into the "corner case" box.
The spec for https://drafts.csswg.org/css-rhythm/#line-height-step says that
The initial value of line-height is
normal
which is defined like this:Actual implementations are know to vary, and in practice the actual numerical value of
line-height: normal
is unpredictable. Ideally authors will not rely on it and manually set theline-height
when they want to useline-height-step
, but we should try to be robust when they don't.If
normal
in a particular browser on a particular os with a particular font is equivalent to1.15
, and on a different browser/os/font combination, it is equal to1.25
, and an author leavesline-height
at the default value, and setsline-height-step
to1.2em
, things will look fine in one browser and not in the other, and the author may not know if they do not test in that particular browser/os/font combination.I think it is quite important to reduce or eliminate this kind of situation, so we should do something.
How about this:
When line
line-height-step
is not0
, thenline-height: normal
is treated asline-height: 1
when computing the used value. This would usually be appropriate (and in the odd case where it is not, it is always possible to set a manual value), and would eliminate variation between browsers, making naïve use ofline-height-step
more robust.