w3c / csswg-drafts

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

[css-inline-3] Tight vs loose fit into a line box #5239

Open fantasai opened 4 years ago

fantasai commented 4 years ago

In today's discussion about how to decide whether content fits, we talked a bit about the models we use for fit. Mostly we focused on the question of “what do we consider to be the size of the inline” when deciding whether it fits, but the other question is what do we consider to be the “container” representing the line box?

Currently we have two models for the height of container:

For an illustration of this, see slide 52 here.

The idea for sizing a line box is, if an item sticks outside of that bounds, it doesn't fit, and we increase the size of the line box to make it fit.

In general, CSS uses model A. This guarantees that there will be no overflow, no overlap of content unless the author specifically indicated the desire for that effect through negative margins or negative leading.

However, for ruby annotations, we use model B. This is a bit risky, but as long as the text is fairly consistently sized and there is only ruby on one side (and the start of the block has enough margin or padding), it works. We increase the height of the line if the author didn't provide sufficient line gaps (which is advantageous in certain typographic environments) but when they do, the ruby fits within that gap.

The question came up, if the effects of slicing down the size of ascent/descent inline down to internal metrics isn't sufficient to get the desired typographical fits, we might consider a more general switch for model B.

I guess the open question is, do we want that, and if so, what does that look like syntactically-speaking?

dauwhe commented 4 years ago
superscript

I went back and looked at the case of an ordinary superscript in text. Even with text-edge: text or text-edge: cap it seems like the sup box intrudes into the half-leading of the previous line. I think you'd have to set text-edge: ex to get the effect in the illustration?

Yellow = ascent/descent bounds for superscript Green = top/bottom half-leading for superscript Blue = top/bottom half-leading for regular text Ascent and cap height metrics for superscript are in red (data is from Adobe Caslon Pro)

Cap height and ex height are shown in red in the diagram (info is from Adobe Caslon Pro).

css-meeting-bot commented 4 years ago

The CSS Working Group just discussed tight vs loose fit into a line box.

The full IRC log of that discussion <fantasai> Topic: tight vs loose fit into a line box
<fantasai> github: https://github.com/w3c/csswg-drafts/issues/5239
<emilio> fantasai: dauwhe made a nice diagram, we had a lot of discussion about this. We recently added the text-edge property to control what is the size of an inline box in terms of deciding what is the size of an inline box
<emilio> ... for the purpose of fitting on a line or not
<emilio> ... which allows us to trim the half-leading and a bunch of other sutff
<emilio> ... deciding whether something fits inside a linebox is deciding whether something fits into our own half or the leading but it may be ok if it leak outside of our half leading if it leaks only into the half-leading of the subsequent line box
<emilio> ... I'd call that loosely fitting. We do this for ruby
<emilio> ... we make the assumption that there's a linebox before and after with the same metrics as the root inline box
<florian> q+
<dauwhe> q+
<emilio> ... do we want to allow this for other kinds of content than ruby and if so what does that look like?
<astearns> ack florian
<emilio> florian: to be clear we don't try to detect collisions nor special-casing for first lines right?
<emilio> fantasai: right, if you enable this you have a decent chance of overlapping content
<astearns> ack dauwhe
<emilio> dauwhe: I drew this because we put a superscript in a paragraph and we break the vertical rythm and we hate this
<emilio> ... text-edge controls how the child inline affects the line height
<emilio> ... to make this work you couldn't even do the text-edge checks on the cap height you need to cut it all the way down to the x-height for the cap not to get into the half-leading of the previous line box
<emilio> florian: I think the text-edge lets us get rid of the green part of the problem, but we're left with the yellow part of the problem
<emilio> fantasai: so with the line layout model you could give negative margins you'd allow overlap up to the margin and not more
<emilio> ... one way to get this is to set margin-top: -half-leading on the element you want to allow bleeding
<emilio> ... but we don't have such a value right now
<emilio> ... various things we could do
<emilio> florian: it seems there are two models, A and B, with ruby using one and regular layout using another, but authors not having the choice
<emilio> koji: do you want to allow bleeding unconditionally or do you want to detect conflicts?
<emilio> fantasai: ruby doesn't detect conflicts so we'd do the same
<emilio> koji: but ruby is safe because it's usually in one side, but generally you may have superscript on one line and subscript in the previous one
<emilio> dauwhe: I'd be willing to take the risk of some ink overlap to preserve the regularity of my line spacing
<emilio> ... in the case shown here I wouldn't have many problems unless stuff goes over the font descent
<emilio> ... if you know the font you're using then it seems worth the risk
<emilio> florian: collision avoidance seems expensive to compute
<tantek> Is there a user accessibility (readability) concern though with overlapping ink that may need to override the web author not minding about some ink overlap?
<emilio> koji: this proposal seems limited to that purpose in the issue
<emilio> ... would like a more general thing
<emilio> fantasai: for example?
<Rossen_> q?
<devsnek> the heck
<emilio> koji: most dtp(?) allows to control the exact line pitch, risking overlapping content, which I think is a good model for CSS
<emilio> ... but this seems only half-way there
<jensimmons> present-
<emilio> florian: dtp seems useful only if you render it in the computer of the author
<emilio> astearns: doesn't CSS allow you to have that setting line-height to a fixed length?
<emilio> fantasai: not really. It's possible with the new line layout model with negative margins
<emilio> koji: I think what I said is in fantasai's (missed)
<koji> s/(missed)/the Absolute Model in page 52 of fantasai's presentation
<emilio> fantasai: so I think that you're proposing an absolute model where we don't care whether stuff doesn't fit at all, while loose has some limits, and I think is good for the author to be able to opt out of some of those
<AmeliaBR> q?
<emilio> ... I think we should not allow to switch it off for the whole page
<emilio> astearns: I like the idea of taking the behavior we already have for ruby
<emilio> ... and expose it to authors
<fantasai> s/opt out of some of those/opt out consciously on specific content, but not to set a mode switch that would allow any amount of conflicts that the author may not even see on their computer/
<emilio> AmeliaBR: on the topic of absolute line spacing we have the vertical-rythm module, but IIUC the way it works is avoiding conflicts but pushing stuff down a whole line
<emilio> ... but this allows to keep some overlap while keeping the vertical rythm
<emilio> dauwhe: everything is tradeoffs but sometimes avoiding the collision is worse than the collision itself
<emilio> fantasai: as long as it is still readable, but there may be cases where not, like if the top of the capital P overlaps with the bottom of the n
<emilio> koji: I think dauwhe's case is that when the author has control of the text and wants collisions instead of separation, and I think it's a reasonable request
<emilio> fantasai: I'm fine with collisions as long as authors are explicit, and the new line layout model allows that via negative margin
<emilio> fantasai: this probably needs a lot more thought and there's not any concrete proposal on the table
<emilio> AmeliaBR: seems like a problem worth solving
AmeliaBR commented 4 years ago

I was playing around to figure out which properties on the superscript element could currently be used to allow a superscript/subscript to extend outside the line box. Negative margin-top doesn't seem to work, but line-height: 0 does (or some fraction less than one that cancels out the overlap region).

Just in case anyone is looking for a workaround until we come up with a proper solution…

faceless2 commented 2 years ago

dauwhe: I'd be willing to take the risk of some ink overlap to preserve the regularity of my line spacing ... in the case shown here I wouldn't have many problems unless stuff goes over the font descent ... if you know the font you're using then it seems worth the risk

...

fantasai: I'm fine with collisions as long as authors are explicit, and the new line layout model allows that via negative margin

We've had a go at implementing text-edge as it's currently specified and I'm not sure that negative margin is going to solve this.

I've put an example at https://jsbin.com/lecudab/edit?html,output. The way this renders with text-edge: ex is:

image

I chose ex as it makes the least contribution to the linebox of all the values currently specified, but even this value pushes the linebox out to the text-bottom edge. The vertical rhythm is still going to be broken with a subscript.

As suggested, I then put a negative margin on the super/subscript - it feels a little awkward as I must also set text-edge to something other than the default of leading to make it apply, even though it's not the "ex" baseline I'm aiming for:

sub {
    text-edge: ex;
    margin-bottom: -1em
}

This made no difference: the margin is applied to the sub but not the replaced content within it, which still contributes to the line-height (although I'm prepared for the reply "you're misinterpreting https://drafts.csswg.org/css-inline-3/#inline-height" on this point).

Even assuming it does apply, I'd chosen an arbitrary "-1em" to try and ensure the margin disappears above the main alphabetic baseline, but with text-edge: ex this pushes the layout bounds under-edge above the over-edge for the subscripted text. The best I can do here istext-edge: ex alphabetic; margin-bottom: -1ex to set the under and over edge of the subscripted text to the "ex" baseline.

But where even the "ex" baseline is outside the default bounds of the line-box (say for very large baseline-shifts, or nested super/subscripts) I'd have to further adjust both the top and bottom margins to ensure they're still within the default bounds of the line box and prevent them from changing the rhythm. It's starting to get very complicated at this point and not at all intuitive.

If all I want is to preserve line rhythm at all costs and in all cases, a value like text-edge: none which means "do not contribute at all to the line height" for this would be a lot simpler.