[csswg-drafts] [css-overflow-3] Intrinsic sizing of elements with continue:discard (e.g. those with line-clamp)

frivoal has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-overflow-3] Intrinsic sizing of elements with continue:discard (e.g. those with line-clamp) ==
The [spec claims](https://drafts.csswg.org/css-overflow-3/#fragmentation):

> The remaining content after the fragmentation break is discarded, similar to if it were `display: none`:
> 
> * It is neither rendered, nor measured as part of the box’s contents for the purpose of finding its min-content, max-content, or automatic block sizes
> [...]
> However, since intrinsic sizes are calculated across all fragmentation containers, this content is taken into account for the purpose of finding the box’s min-content and max-content inline sizes (see CSS Fragmentation 3 §5.1 Breaking into Varying-size Fragmentainers).

I'd like to dispute the assertion about intrinsic sizes.

The assertions about intrinsic sizes made in CSS Fragmentation §5.1 are about the intrinsic sizes of elements of the fragmented flow. Here we are talking of the size of the fragmentainer itself. Since the content of the fragmented flow and the fragmentainer come from the same element, it is tempting to take a shortcut and say that these are the same, but just like the intrinsic height / width of a (multi)column isn't the same as the intrinsic size of the content of the multicol, this doesn't have to be the same.

I think that here, the answer that makes the most sense is to say that the intrinsic sizes of the fragmentainer are calculated using content from the start to the first forced break if any, or to the end of the content if there is no forced break.

If you put a `line-clamp: 3` element inside an grid cell that is intrinsically sized in the block direction, you'll get a tight fit around the 3 lines, as an author would expect, instead of 3 lines in a grid cell sized to fit 127 or however many the element had.

If you put a `continue: discard` element without a forced break in an auto-sized grid cell, you'll get a cell large enough to fit the whole content, which is also the reasonable thing to do.

In the inline direction, the same logic applies.

For the inline max-content size. If you have for instance `foo { continue:discard} foo *:first-child {break-after: region; }` an author would also expect the max-content size to tightly fit around the content before the break, rather than being large enough to accommodate content that isn't there.

For the inline min-content size, same thing. I feel that this is less critical, since using the whole content could result in lines that are too long if the longest word/atomic-inline is in the discarded content, and that's not a catastrophic failure, but going to the first forced break still leads to better results.

In terms of the box tree, this can be explained by saying that an element with `continue:discard` creates an anonymous fragmentainer box, whose intrinsic size works as described above, and then the fragmented flow (i.e. the content of the element) is laid out inside it, using its own intrinsic size and layout computations.

----
Note 1:

Using forced breaks only, instead of forced or unforced breaks, is necessary to avoid loops in cases such as CSS-Grid where the formatting context containing the continue:discard element has characteristics that use the intrinsic size of the items to change the amount of space available for them. If we were using unforced breaks as well, the intrinsic size of the grid item would change based on the size of the grid cells as more or less content fits, and in turn the grid cells would change in reaction to the change in intrinsic size, possibly ad infinitum.

With forced-break-or-end-of-content, the intrinsic size does not depend on layout, so there's no loop.

----
Note 2:

Level 3 of css-overflow does not attempt to define `continue:fragments`, and when we do define it, we can, but do not necessarily have to set intrinsic sizing of the fragments to the same logic as what we pick for `continue:discard`, so what we define here does not constrain us for what we'll do there.

(So, if you don't care about `continue:fragments`, stop reading here)

If we want to think about it a bit nonetheless, and check if we could apply a similar logic:

* from the point of view of laying out the fragmented flow, there's no problem about having differently sized fragmentainers, each with their own intrinsic size. The CSS-BREAK spec has a section which defines "Breaking into Varying-size Fragmentainers", so we can just apply that, and all is fine.

* from the point of view of laying out the fragmentainers themselves inside something like CSS-Grid, it is a little more involved. In the case of gird cells whose size depend only on what's inside them, everything still works fine. However, we do have to be careful not to introduce loops when a cell's size depends on the size of other cells. There's not more difficulty about the first fragment than there is for `continue:discard`, but for the second fragment, If the intrinsic size depends on where in the fragmented flow it starts, then the actual layout (not just intrinsic size) of the first fragment would affect the intrinsic size of the second, which would be bad. Determining the intrinsic size only from forced-break to forced-break solves that from a computation point of view, and I think it gives a reasonable layout in enough cases, so that's probably a good solution. But we can worry about that when we get there: stable solutions exist, and we're not trapped by compatibility with `continue:discard`, so we'll be able to debate the pros and cons of various approaches then.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/2945 using your GitHub account

Received on Saturday, 21 July 2018 14:08:47 UTC