w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.42k stars 652 forks source link

[css-rhythm-1] Avoiding accidental double spacing #938

Open frivoal opened 7 years ago

frivoal commented 7 years ago

The spec for https://drafts.csswg.org/css-rhythm/#line-height-step says that

It is usually recommended to set the line-height lower than the step unit. The used line height can increase due to several factors such as the use of vertical-align or font fallback.

The initial value of line-height is normal which is defined like this:

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 <number>. We recommend a used value for 'normal' between 1.0 to 1.2. The computed value is 'normal'.

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 the line-height when they want to use line-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 to 1.15, and on a different browser/os/font combination, it is equal to 1.25, and an author leaves line-height at the default value, and sets line-height-step to 1.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 not 0, then line-height: normal is treated as line-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 of line-height-step more robust.

kojiishi commented 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.

frivoal commented 7 years ago

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.

fantasai commented 7 years ago

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

kojiishi commented 7 years ago

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.

kojiishi commented 7 years ago

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.

kojiishi commented 7 years ago

Added i18n label because this proposal will cause lines to overlap for some scripts.

kojiishi commented 7 years ago

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.

kojiishi commented 7 years ago

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.

  1. I understand the interop problem with line-height: normal.
  2. I understand there are cases where rhythmic sizing may make the issue (1) worse.
  3. I believe this proposal sacrifices a CSS readability feature for tall scripts.
  4. I think this proposal is net negative, given (3) looks more critical than (1) to me.
  5. I mildly prefer solving the original issue (1) altogether, not only the worse one (2).

Happy to discuss more if anyone can come up with new proposals, or disagree with me on 3-5.

RByers commented 7 years ago

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.

frivoal commented 7 years ago

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:

Proposal: line-height-step: none | [ <length> [ safe | unsafe ]? ]

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:

⇒ Same as now

Now, let's assume a font for which line-height: normal gives 1.3

⇒ The step size is a little larger than expected, allowing the rhythm to work without creating blank lines everywhere

kojiishi commented 7 years ago

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?

kojiishi commented 7 years ago

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.

frivoal commented 7 years ago

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.

dbaron commented 7 years ago

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.

frivoal commented 7 years ago

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.

kojiishi commented 7 years ago

@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.

kojiishi commented 7 years ago

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.

css-meeting-bot commented 7 years ago

The CSS Working Group just discussed Avoiding accidental double spacing.

The full IRC log of that discussion ``` topic: Avoiding accidental double spacing github issue: https://github.com/w3c/csswg-drafts/issues/938 github topic: https://github.com/w3c/csswg-drafts/issues/938 florian: this is about avoiding accidental double spacing, this might happen if an author sets line height step to 1.3 em, and the default font using line-height normal turns out bigger than 1.3 em in another font the line-height might be calculated at double height the previous proposal was to make the height deterministic but koji pointed out that line-height normal is useful as it avoids overlap with long ascenders and descenders florian: has a proposal for this when you have something with a tall line-height you want it to be double, when it inherits this is a feature when you set it, you never want to accidentally make the line-height step smaller than the natural line-eheight soemtimes you want to do it on purpose proposing to add a safe /unsafe keyword pair defaulting to safe current behaviour is the unsafe one dbaron: I understand but think it is a problem the check is whether the line-height step is smaller than th eline-height and if so make the step bigger the 2 pieces I am concerned about, 1 is that normal is a computed value of line-height having that go back and influence line height step doesn't seem as if it will work we do sometimes have font metrics influence computed values florian: you need ot take th eline-height unit value as the lh unit depends on it dbaron: so maybe that is ok, the other thing is that if you use text for more than one font we claim you end up creating a box of the size of the. line-height around both sets creating a height that is larger than the line-height fantasai: thats a general problem dbaron: to the whiteboard florian: does this change what line-height normal means dbaron draws a Chinese character and a Latin letter dbaron: demonstrates lining up characters on the whiteboard dbaron: suppose these come from different fonts dbaron draws the ascent and descent on the chinese character dbaron then draws the ascent and descent on the Latin letter, which is a little bit lower florian: which is the primary font and which is the fallback dbaron: it shouldn't matter as per the spec fantasai: I think there is a conflict in the spec dbaron: the number line-height is 1.26 font size 16px, so we want a 20 pixel box round each of these dbaron demonstrates where the line-height boxes are around the two characters (dbaron is using a numeric line height in place of normal, because normal could result in varying line heights; didn't want to deal with the complexity yet) dbaron: end up with a line box height bigger than the line-height dbaron notes that because the ascent plus descent plus half-leading of each adds up to 20px, but they are offset by 1px, the total line height is 21px fantasai says the CSS2.1 spec says two contradictory things, one of which is that florian: in this case if you started with a line-height step of 30 pixels you wouldn't get double spacing dbaron: the designer might have fonts that have the same box and others have different boxes and get the double spacing https://github.com/w3c/csswg-drafts/issues/391 florian: for it to fail that way you need multiple fonts falling back to each other fantasai: I think this point is really important, it is a critical flaw in how it works when you have boxes of the same height, the CSS2.1 spec says 2 different thinks you get that result and also get 20 pixels out of that so we need to fix that in order for line-height-step to be at all robust and not flaky we need to fix it myles: Gecko and spec agree with dbaron's example, WebKit would calculate the height and add spacing to either side to make it equal (The spec says two contradictory things, and supports both Gecko and WebKit's interpretations depending on which sentence you read in the paragraph describing this) I don't think that's actually what Gecko does dbaron: oh, yeah, that is what the spec says -- add the half-leading after unioning the character heights astearn: this is one crucial instance, but initially you were talking about making step sizing in the safe mode that would increase itself if it encountered a large line-height florian: where you have set your step size accidentally smaller than the computed value of line-height fantasai: can we resolve on fixing this? https://github.com/w3c/csswg-drafts/issues/391 koji: how do you compute line-height normal to pixels dbaron: it's more like a number than any other kind of value but it does a thing based on the font myles_: it is based on the default font Here's the thing I drew on the whiteboard: https://lists.w3.org/Archives/Public/www-archive/2017Apr/att-0006/IMG_20170420_102101.jpg (although as myles__ pointed out, I was wrong) the point I wanted to make that you use step sizing to create vertical rhythm. Creating a 'safe' version that avoids double spacing and breaks the rhythm is counterproductive florian: is there a definition for the used value of line-height, if you have normal and know the font fantasai: at computed time the lh unit needs to map to an actual value dbaron: I think you get it from the first available font florian: the value of the line-height property does it change based on content on the line? does that property vary per line? myles_: no properties do not vary per line florian: you can't change the primary font per line dbaron: I think florian is talking about multiple lines splitting the same element the computed value of line-height normal is normal so if you are asking what lh does, when you have line-height normal use the first available font in the font list florian: not only is the value normal, but the value of line-height 1.2 is 1.2 dbaron: let's file a spec issue florian: what makes this impossible dbaron: spec needs to say how to compute to an abs length, probably using the primary font florian: do you need to do layout to figure out the pixel value of line-height? dbaron: for the lh unit or for layout? florian: not talking about the line box what does the UA pick the number based on? fantasai: I think you assume this gets computed by a number and used as that number for layout calcs, used as a length to figure out the leading that conversion happens per font in the text myles_: webkit does this fantasai: if you don't have a value for the entire run, how can you work out the line-height for a single value ok, filed https://github.com/w3c/csswg-drafts/issues/1253 on css-values-4 myles_: (answering q) we do a bunch of stuff for the width then we calculate heights and place vertically fantasai: for each char you find ascent and descent, get a value, if it is not the line-height increase or decrease on both sides to get the line-height dbaron: do you then use the normal? dbaron: use line-height normal, a single element on the line, font fallback is happening in the line, fonts have different etrics for line-height normal and ascent and descent ... you take the ascent and descent, where do you get the number for normal myles_: we don't dbaron: Gecko includes the external leading florian: how is this not a violation of 2.1? koji: this sentence contradicts other parts of the spec dbaron: that sentence was written in the olden days s/we don't/we don't; we take that value with no extra leading/ dbaron: it assumes defaulting to what the font says https://drafts.csswg.org/css2/visudet.html#inline-non-replaced koji: describes content box height fantasai: the content box height has no effect on layout dbaron: it matters re leading around it fantasai: but this section is not related to line-height normal dbaron: it can change the size of things, because the leading changes the content height, the middle of where the content height is does matter to layout astearn: we're not really addressing the rhythm issue here, though we found bugs in other specs florian: do we have an issue to define the line-height unit based on primary font dbaron: pasted such an issue earlier florian: the issue I proposed is to define the same way koji: this is based on font metrics of the primary font in safe mode florian: when it inherits, is specified. It doesn't depend on the font astearns: you set your vertical rhythm for body text but the heading is bigger what happens florian: the line step height will double to keep the rhythm gets the unsafe value from the pixel not magic, doing this based on a keyword, unsafe is current behaviour. safe will cause the bigger line-height behaviour koji: does this change based on inheriting? florian: no magic with inheriting ok, filed https://github.com/w3c/csswg-drafts/issues/1254 on line-height:normal definition in CSS 2.1 florian: how well this works depends on how we fix 2.1, it doesn't make things worse koji: I don't see it saves much, maybe some cases people think it is better fantasai: keyword on line height setp to us line-height astearns: that would make double spacing more likely florian: you don't want to be exactly the line-height, needs to be just a bit more astearns: step sizing could be a percentage of line-height florian: either line-height is a number and works, or it isn't if you want to set your step smaller than the line-height, set it explicitly with unsafe then it will not get adjusted up Koji: on web, due to small screen real estate, people set grid to fraction (half) of the desired line height astearns: that happens in print as well koji: I understand some cases it helps, given complexity vs benefit florian: it is very frustrating when people won't use a browser if it breaks, the outcome of not dealing with this could cause problems with different sized fonts, in one browser double heights might happen based on default sizing fantasai: having a layout system that breaks badly when fonts get substtuted is bad double spacing is bad dbaron: authors should not have to write a number in their CSS that has to be right based on the font the user has florian: the feature currently requires users pick a value dbaron: the dev currently has to write line-height 3 or 20 pixels, Chrome might switch to double spacing based on one value, Firefox might pick another value, a subtle difference means you get double spacing in one browser and not another dbaron: Gecko has had to reduce line-height they compute for webcompat issues fantasai: we don't want more of these situations astearns: should we come up with a way of making step sizing safer, we haven't come up with a resolution on that ```
dbaron commented 7 years ago

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:

(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.

dbaron commented 7 years ago

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.

frivoal commented 7 years ago

I believe I understand how your proposal work. But I will need to think about it for a while to figure out if:

  1. solves the problem ( I think it does)
  2. solve the problem better than my thing (I don't know, that might depends on how line-height works)
  3. Whether it will make sense to authors and let them express the thing they want in an understandable way (I do not know yet).
dbaron commented 7 years ago

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.

kojiishi commented 7 years ago

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:

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.

dbaron commented 7 years ago

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:

kojiishi commented 7 years ago

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?

kojiishi commented 7 years ago

Oh, wait, I see what missed...

kojiishi commented 7 years ago

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:

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.

kojiishi commented 7 years ago

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.

kojiishi commented 7 years ago

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.

  1. There was a feedback that different browsers/platforms/fonts to use different steps is the biggest problem we must solve.
  2. The problem 1 above applies only when 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.
  3. There are multiple proposals on this issue, two from @frivoal in this thread, one from @dbaron above, and another from @fantasai not baked well yet. I admit I don't fully understand @frivoal's yet (sorry) but given the 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.
  4. Given the primary target of the feature is East Asians, fallback is highly possible. When system fallback happens, the used steps will vary by installed fonts. It'd be not easy to mitigate this case.
  5. If in the future we changed our mind and wanted to apply line-height-step to line-height: normal, we could add a keyword, like the one in @frivoal's proposal.
upsuper commented 7 years ago

The problem 1 above applies only when 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.

Really? It doesn't seem to me so. IIRC, there is still inconsistency among browsers when there are inline boxes and font fallback involve.

upsuper commented 7 years ago

Oh, I was probably wrong. The used line height should be consistent when the computed value is not normal.

frivoal commented 7 years ago

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.

litherum commented 7 years ago

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)

frivoal commented 7 years ago

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.

css-meeting-bot commented 7 years ago

The CSS Working Group just discussed Avoiding accidental double spacing.

The full IRC log of that discussion <dael> Topic: Avoiding accidental double spacing
<dael> Github topic: https://github.com/w3c/csswg-drafts/issues/938
<dael> Florian_: I think we shouldn't rehase that issue in github. I think we need to sort out another issue first. We had been talking about what line-height normal means at F2F and discovered we don't even know what line-height: number means.
<dael> koji: There are details to get out. As long...in terms of line-height consistancy, I think dbaron confirmed it's consistant.
<dael> Florian_: I don't think we concluded. WE said prob is, but we have 3 behaviors on the white board. We weren't sure.
<dael> koji: All on consistant for line-height
<dael> Florian_: No they're not.
<dael> koji: They were.
<dael> Florian_: 2 are, one isn't.
<dael> Florian_: The black behavior does not result in the same line-height as blue a nd red.
<dael> Florian_: We weren't sure which Edge did. We didn't have full answers.
<dbaron> Only one of the three is consistent for line-height if you have font fallback
<dael> Florian_: My prop on double s paces depending on line-height.
<fantasai> diagram: https://lists.w3.org/Archives/Public/www-archive/2017Apr/att-0008/IMG_20170421_173959.jpg
<dael> koji: I think I have tests on this already.
<dael> Florian_: If you have tests, when were they shared?
<dael> koji: In this issue.
<dael> koji: As far as I tested it's interop.
<Florian_> https://github.com/w3c/csswg-drafts/issues/1254
<dael> Florian_: When we discussed at F2F no one knew for sure. If you do know ^ is where we discussed that.
<dael> astearns: koji can you post a link to your test cases?
<koji> http://output.jsbin.com/xekuhu
<astearns> http://output.jsbin.com/xekuhu
<dael> astearns: Is it ^?
<dael> astearns: There we go.
<dael> Florian_: Okay.
<dael> astearns: koji can you desc what it's checking?
<dael> koji: This is a test case we discussed. 5 in the graph and line-height nromal. You can see the line-height is same. If you hae 5 line-height it's maybe different. 0,4 have 1.2, 1.5, 1.8
<dael> koji: You can see it's consistant height.
<dbaron> Does this testcase have font metrics that would trigger the issues we discussed?
<dael> Florian_: I can't figure out which browser is what color.
<dael> fantasai: You need a case with fallback in the line. Where you have difference scripts all on the sameline. Have that trigger different fonts with different ascent & decent metrics.
<dael> MaRakow: You need a font with crazy high and crazy low ascent/descent.
<MaRakow> s/MaRakow/???/
<myles_> s/MaRakow/myles_/
<dael> Florian_: I think this is a bit too tricky on the fly. Until we call agree what line-height: number and line-height: normal means it'll be hard to solve.
<dael> Florian_: If we agree enough that size is the same that could be enough to discuss. Doc about behavior isn't there.
<dael> koji: I thought [missed]
<dael> astearns: I think I heard you say browsers agree on line-height, but not glyph in line-box. Correct?
<dael> koji: Yeah. one this we agreed is to match existing impl. If they all agree on line-height: n umber I don't see problems.
<dael> Florian_: I don't think we established they agree.
<liam> s/not glyph in/not glyph-position in/
<dael> fantasai: We said impl will agree if they confirm to CSS2 because we agreed to change CSS2 to say that the black behavior is not allowed. So if immpl follows spec line0height will be that number. If impl don't follow they have to change.
<dael> dbaron: I don't htink that's what we agreed.
<dael> Florian_: I think that was a preliminary conclusion.
<dael> 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.
<dael> astearns: Did I hear myles_ volunteer to make test fonts?
<dael> myles_: I can do that easily.
<dbaron> s/with multiple/if there are multiple elements on the line/
<dael> astearns: Thank you.
<Rossen_> https://lists.w3.org/Archives/Public/www-archive/2017May/0000.html
<myles_> please ACTION me
<myles_> bkardell_: there are many fonts named that 😇
<myles_> (test fonts)
<dael> astearns: I think we need to get past this Q about what CSS 2 will say about line height and if impl will be able to match. Then figure out cases where that's not enough for consistant line height.
<dael> astearns: Seems they're pre-requisite to figure out step height.
<dael> astearns: koji is it alright ot move on?
<dael> koji: Yeah. I'll re-read the discussion.
<dael> astearns: I wouldlike to see progress. I'll see what I can do to get that going. I think myles_ making the fonts will be a big help.
<Florian_> agreed
kojiishi commented 7 years ago

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.

kojiishi commented 7 years ago

Re-read the IRC log, appreciate your confirmation: @frivoal @dbaron

  1. So the red and the blue from the F2F diagram provides consistent height, though baseline position may not.
  2. The black one is not consistent height.
  3. We confirmed Gecko and WebKit are red (though the diagram indicates Gecko is blue) and Blink is blue, though when I commented Blink and WebKit are more likely the same on this behavior, @litherum wasn't sure.
  4. @atanassov wasn't sure whether Edge does red, blue, black, or something else in the F2F.
  5. By running a test with system fallback of tall scripts @fantasai and I used to verify Blink/WebKit/Gecko behavior on the night before, Edge showed the consistent height, so @fantasai and I thought the black is not allowed, and disallowing black does not require anyone to change, but maybe we didn't share this, don't remember.
  6. As long as we agreed on heights are consistent, editing CSS2 and CSS-Rhythm do not block each other, we can parallelize them.
  7. @upsuper thinks it's consistent in the comment above.

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?

kojiishi commented 7 years ago

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.

litherum commented 7 years ago

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 on some text. I wanted to compare the case of 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.

lineheight.zip

kojiishi commented 7 years ago

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.

kojiishi commented 7 years ago

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.

frivoal commented 7 years ago

@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:

frivoal commented 7 years ago

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.

kojiishi commented 7 years ago

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.

  1. This issue originally starts from disabling a hard-coded value in UA, assuming it exists. At that point, I heard some members supported the idea, but IIUC not all spoke their opinions.
  2. 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".
  3. @dbaron commented in mozilla.dev.platform that he's opposed because if vertical rhythms are applied to font-dependent layout, it can produce serious compatibility problem.

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.

  1. The @dbaron's comment above was not shared with WG.
  2. While we now understand what will happen when vertical rhythm is enabled in font-dependent layout document, we haven't discussed much about side effects if we disabled either one.
  3. We heard opinions from several people at point 1 of the history, but not after 2.
  4. Even at point 1, IIUC, we haven't heard opinions from other implemeters than Blink/Gecko.

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:

  1. @dbaron, is it possible for you to explain your comments at mozilla.dev.platform, and up-to-date thoughts if there were any changes since then?
  2. @FremyCompany (or someone at Edge team) could you mind to consider sharing your thoughts?
  3. @litherum (or someone at WebKit team) could you mind to consider sharing your thoughts? I remember you were supportive in April 2016, but quite a long time has past. Also, this topic would require Line Grid to change the behavior, which WebKit ships today.

@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.

frivoal commented 7 years ago

@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.

kojiishi commented 7 years ago

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?

tabatkins commented 7 years ago

@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?

FremyCompany commented 7 years ago

@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.)

kojiishi commented 7 years ago

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.

tabatkins commented 7 years ago

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.