w3c / csswg-drafts

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

[css-contain-2] contain:size shouldn't fragment as monolithic #5648

Open fantasai opened 4 years ago

fantasai commented 4 years ago

Currently the spec says:

Size containment boxes are monolithic (See CSS Fragmentation 3 §4.1 Possible Break Points).

I think what we want to say is that the box is treated as fixed-size for the purposes of fragmentation (it cannot get larger, only split across pages), but the content inside it can fragment normally.

frivoal commented 4 years ago

what we want to say is that the box is treated as fixed-size for the purposes of fragmentation (it cannot get larger, only split across pages)

Well, yes we mean that, but also:

As long as that's respected, when we do fragment, we don't have to visually slice the content, and we could break it cleanly between lines or at otherwise allowed fragmentation points. However, both are kind of bad (which is why we should avoid fragmenting in the first place when possible), so I'd be inclined to let that up to the UA though: If the box is more than tall enough to fit all its content, it's best to do fragmentation of the content cleanly. But this might underfill the first(s) fragments, and put too much content in the last one. If that last fragment isn't tall enough to accommodate all that's pushed into it, it might be ok to let it overflow, or it might have been better to slice the content instead of fragmenting it cleanly if that would avoid overflow.

For instance, if the unfragmented box is just tall enough to fit 3 lines, and it gets fragmented in 2 equal parts, you can either put 1 line in the first and 2 in the second letting that last line overflow (and possibly overlap with subsequent content), or you can put 1.5 lines in each. Both seem bad, so I'm not sure I want to force UA's hand.

So, overall, I think calling them monolithic is the right call, but we might want to add an allowance UA discretion about how they slice or fragment the contents when they do need to fragment.

tabatkins commented 4 years ago

Yeah, Florian covered all the points. We did indeed intend for them to be monolithic, as that's the closest concept we have to the "contents don't matter" constraint that we want.

frivoal commented 3 years ago

@fantasai, are you OK with the conclusion above?

frivoal commented 3 years ago

Closing, and moved the discussion of whether we want to do anything smart inside of a broken monolithic element to https://github.com/w3c/csswg-drafts/issues/6326

fantasai commented 2 years ago

Well, yes we mean that, but also:

  • that you should avoid fragmenting them if possible (see below for why)
  • and if you do fragment them, the point at which the box is split should not depend on the layout of its content. The size of each fragment should only depend on the size and position of the box, not what's in it.

In that case

So, overall, I think calling them monolithic is the right call, but we might want to add an allowance UA discretion about how they slice or fragment the contents when they do need to fragment.

Monolithic items by definition do not fragment the content inside them. They can only slice. If you want to fragment, you can't call them monolithic.

frivoal commented 2 years ago

break-inside: avoid isn't break-inside: impossible. It will do the part about avoiding fragmentation if possible, but it doesn't do the part where if you do have to break, you're not allowed to break it in a way that:

We have to add additional constraints for that. Monolithic achieves that.

I do agree that it is more constraining than strictly necessary: an alternative strategy could be to have each fragment be sized exactly as if you had sliced, but within that space, to allow for ordinary fragmentation. In under-filled elements, that could give better results. However, nobody is doing that today. I'd rather keep it simple for L1, and possibly relax things a little in later levels.

fantasai commented 2 years ago

@frivoal As I said twice earlier (and you keep ignoring), if you have a fixed-size box, the total size does not change based on the fragmentation of its content. contain: size is never auto-sized, so regardless of being monolithic or not the total size won't change. But if you classify it as monolithic, it's not allowed to fragment its contents.

frivoal commented 2 years ago

As I said twice earlier (and you keep ignoring)

I have not been ignoring that. There's another requirement I have pointed to, which you seem to have missed:

The size of each fragment should only depend on the size and position of the box, not what's in it

&

you're not allowed to break it in a way that […] makes the size of each fragment depend on the content

Merely having a fixed-size box does not guarantee that. See http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=10671

If you hover over the boxes, you'll see that the size of the fragments does vary based on the content (even though the total size does indeed not vary).

css-meeting-bot commented 2 years ago

The CSS Working Group just discussed [css-contain-1] contain:size shouldn't fragment as monolithic, and agreed to the following:

The full IRC log of that discussion <fantasai> subtopic: [css-contain-1] contain:size shouldn't fragment as monolithic
<fantasai> https://github.com/w3c/csswg-drafts/issues/5648
<fantasai> github: https://github.com/w3c/csswg-drafts/issues/5648
<astearns> github: https://github.com/w3c/csswg-drafts/issues/5648
<heycam> florian: CSS Contain has several types of containment
<heycam> ... all these are establishing changes to how CSS normally behaves, to reason about inside/outside the element, breaking dependencies
<heycam> ... what's going on inside an element doesn't affect the outside
<heycam> ... we have size containment, the goal being when the inside changes, the size of the element doesn't
<heycam> ... and in particular within that, we want to deal with size changes in the case the element is fragmenting
<heycam> ... for that we have a double goal. 1. regardless fo how the element fragments, its total size shouldn't change. but nore than that, the size of the fragments shouldn't change either
<heycam> ... the spec says applying size containment causes the element to be monolithic
<heycam> ... fantasai opened an issue to say it doesn't need to be
<heycam> ... she correctly poitns out size containment causes the element to be fixed size
<heycam> ... so the total size of the element won't vary, regarldess of the breaking point
<heycam> ... but making it fixed size does not guarantee the fragment sizes won't change
<heycam> ... so I think we need something more than merely making the element fixed size
<heycam> ... I agree making the element monolithic is slightly overkill, in the sense that it will guarantee that not only the total size of the box and all fragmnets won't change, but it also means the content of the element will not be fragmented and will be sliced
<heycam> ... which isn't actually necessary in this case
<heycam> ... as long as we guarnatee fragment sizes to not change, we can still allow fragmentation
<heycam> ... fixed size fragments but content fragments is not a thing we have currently
<heycam> ... preference is to stick with the existing spec requirement that all size contained elements become monolithic, because it fulfills the requirement and is what is implemented
<heycam> ... in some later level possibly relax this to not be monolithic as long as you fulfil these specific constraints
<heycam> ... could do that without trouble, any implementation compliant today would be compliant in the future
<heycam> ... but this is the last open issue on css-contain-1
<heycam> ... not sure it's so interesting to change the spec to allow behavior nobody has at this point
<florian> http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=10671
<heycam> fantasai: that seems very weird to me
<heycam> ... don't think it's supposed to do that
<heycam> florian: it's interoperable
<heycam> fantasai: it should be drawing the box all the way to the bottom of the page, and not leaving a gap when it fragments
<heycam> florian: the total size does stay fixed, btu the size of the fragments doesn't
<heycam> fantasai: drawing the box sides all the way down to the end of the page or column, rather than ending at the fragmentation point, then the size of the fragments would not change based on the fragmentation position
<heycam> iank_: all of the fragmentation engines for most cases, when you fragment, you'll typically consume the remaining fragmentainer space
<heycam> fantasai: that's what I was epxecting to happen
<heycam> florian: Safari, Chrome, and Firefox all do this
<heycam> ... three line element fragment, just tall enough to contain the three lines, but the fragmentainer containing the element is 2.5 lines high. so the first fragment will be 2 lines, the third fragment will be 1 line. so there's a 0.5 line gap at the end of the first one
<heycam> ... whether that's the case or not depends on the content of the element
<heycam> ... maybe this is an interoperable spec violation, but I'm not convinced it's a spec violation
<astearns> The fragment heights stay the same in blink, but adjust in gecko
<heycam> fantasai: that's super weird. I wonder what's causing this to happen
<bradk> Wouldn’t box-decoration-break: clone cause the fragments to grow?
<heycam> fantasai: I could undersatnd if engines were like "oh for web compat reasons we can't conusme the extra space", but even when it's auto, it's not consuming down to the fragmentainer
<heycam> florian: because here we're not in a monolithic case, it doesn't want to have one full line of content [...]
<heycam> fantasai: the fact it's not working for auto is disturbing
<heycam> florian: that's the current behavior, and doesn't work for contain:size
<heycam> ... I propose sticking with monolithic for level 1, then maybe relaxing in a later level
<heycam> fantasai: rather defer the issue
<heycam> florian: would you object to the monolithic beahvior being allowed?
<heycam> fantasai: no, I think it's fine to allow that
<heycam> florian: all implementations behave this way, and you're agreeing it should be allowed. is it worth blocking the spec to make a change that's not testable and not invalidate any implementation?
<heycam> fantasai: I said I don't mind deferring
<heycam> RESOLVED: Not make any changes to css-contain-1, possibly relax the monolithic requirement in later levels
frivoal commented 2 years ago

So, while this issue is handled (by deferring it) for L1, in L2 and later, we could relax the requirement a little.

Currently, we have:

Size containment boxes are monolithic

I believe we could replace that with:

Size containment boxes are quasi-monolithic

and define quasi-monolithic boxes as something like:

Quasi-monolithic boxes are similar to monolithic boxes:

  • forced breaks within a quasi-monolithic box must be ignored by the box’s own fragmentation context
  • quasi-monolithic boxes should not be fragmented
  • if a quasi-monolithic box needs to be fragmented, the box is sliced at a point which does not depend on the box's content, only on its size and its position within its fragmentation context.

However, unlike monolithic boxes, when a quasi-monolithic box is thus broken up, its content may be fragmented and laid out normally within each of the fragments instead of being graphically sliced—although graphically slicing is also allowed.

We could obviously do the same thing without introducing the new term and inlining the effects into size containment, but I suspect it's easier to read if framed this way.

bfgeek commented 2 years ago

it should be drawing the box all the way to the bottom of the page, and not leaving a gap when it fragments

For the given example this would only be true if multi-col had column-fill:auto instead of column-fill:balance as is the fragment is consuming up until the fragmentation line.

frivoal commented 2 years ago

@bfgeek To me, the point is: without additional constraints, it may be true that the fragment consumes all the space, but it may not be. And not only is the actual space consumed dependent on the properties of the fragmentation context (which is fine), it also depends (at least in some cases) on the content of the fragmented box, which is not fine in the case of size containment.

Making size contained elements monolithic is sufficient to solve the issue, but is more than strictly necessary.

I think that creating a notion of quasi-monolithic (roughly) defined as above, and calling for size-contained elements to be that would dial down the requirements to what is strictly necessary, while keeping them sufficient.

frivoal commented 2 years ago

Agenda+ to propose https://github.com/w3c/csswg-drafts/issues/5648#issuecomment-1240067326

css-meeting-bot commented 1 year ago

The CSS Working Group just discussed [css-contain-2] contain:size shouldn't fragment as monolithic.

The full IRC log of that discussion <astearns> topic: [css-contain-2] contain:size shouldn't fragment as monolithic
<astearns> github: https://github.com/w3c/csswg-drafts/issues/5648#issuecomment-1240067326
<dandclark> florian: Situation is size containment has requirements about fragmentation we need to satisfy for it to work.
<dandclark> ...: Reused frag. of monolithing elements because if fulfilled reqs but it does more. Solves problem but with unecessary side effects. Can we relax solution to solve prob without side effects?
<dandclark> florian: Size containment requires size of element doesn't change when content changes, and if element isfragmented, size of fragments don't change
<dandclark> ...: COuld have first without second if move fragmentation point
<dandclark> ...: By saying size-contained element is monolithic, do get that property.
<dandclark> ...: Slice the element <missed> and that solves the problem.
<dandclark> ...: If the element contains content, maybe interesting in some scenarios the boxes themselves to that but the content is allowed to fragment in fixed-size fragments.
<dandclark> ...: If have 3 lines of text in element and frag point is in middle of second line, take the entirety of second line and put it in next fragment
<dandclark> ...: 2nd and 3rd line could fit in second fragment without overflow
<dbaron> sounds a lot like printing on paper
<dandclark> ...: Could be interesting to allow browser to either slice or allow content, but allow fragmentation within these sizes.
<dandclark> ...: Should we do this? I don't think any browser does now.
<iank_> I slightly prefer leaving as is
<dandclark> ...: But could be interesting to allow them to
<dandclark> iank: The way that balancing works is that it does need to know about contents and where you slice
<dandclark> ...: and that has depenency on height. Also engines don't implement fragmentation primitives well. Hesitant about adding another
<miriam> q+
<dandclark> ...: especially for such a narrow use case
<dandclark> ...: So prefer leaving it
<astearns> ack miriam
<dandclark> miriam: As container queries beome more popular, how much of an edge case [cut off]
<dandclark> iank: This is only needed when got full size ontainment or containment in block axis
<dandclark> ...: Not needed in inline axis, which is dominant case for container queries
<dandclark> florian: I think that's true, havent thought about it a lot
<dandclark> florian: way I was proposing to address was to invent something to size the content the same; don't require but allow normal fragmentation
<dandclark> ...: It's just an allowance, don't have to take it
<dandclark> ...: Theoretically it would be fine. But only worth speccing if there's interest in pursuing it.
<dandclark> ...: Another solution is to defer it and look again in 5 years
<dandclark> ...: Not time sensitive since it's an allowance only anyway
<dandclark> iank: Don't have immediate interest. Prefer leaving as monolithic at the moment. Can change later if there's demand.
<dandclark> ...: There's demand for strongly making elements monolithic.
<dandclark> ...: Which capability doesn't exist now.
<dandclark> ...: There are cases where break inside avoid <missed>. I can raise separate issue about that
<dandclark> florian: My sense is for this issue, defer it long term. Nothing wrong with proposed solution but no point if no one wants to do it.
<astearns> ack fantasai
<dandclark> ...: Can close issue, or mark deferred.
<dandclark> fantasai: If want to allow in future, should put it in spec, otherwise people won't know we considered it.
<dandclark> ...: If think it's bad idea, should close no change
<dandclark> iank: Not sure if good or bad idea. It's ehhh.
<tantek> do we already link to it in-context in the spec as an open issue? so implementers can be more aware of it?
<dandclark> fantasai: People make web page, use containment stuff. Then try to print the doc. Do we think it's best to cut lines in half?
<dandclark> ...: I expect contain to be used all over the place. So significant amount of printed content will be cut in half.
<dandclark> iank: Disagree w/ premise. Inline size containmnent will be used heavily, but full size containment not that prevalent.
<chris> Havent seen bisected lines of text on printing since, like, Netscape 2 or something
<dandclark> astearns: Out of time. Will leave issue and keep discussing.
mirisuzanne commented 1 year ago

With 'app' style layouts with independently scrolling sections, it's entirely possible that 2-axis size containment will become more popular as well as 1-axis. Those layouts aren't generally relying on fragmentation, but that could become an issue when printing. I do tend to lean towards improving fragmentation wherever we can. From my perspective, the fact that fragmentation is poorly supported and not interoperable today is a problem we should be fixing, not a solid argument against making additional improvements.

frivoal commented 1 year ago

As long as size containment is used, there will be cases where people end up having both size containment and fragmentation happen together, at the very least because people occasionally print stuff. I think the behavior proposed here is strictly superior to what the spec currently says: it would allow what the spec currently says anyway, but would also allow browsers to not slice lines in cases where that's practical.

For instance, if the unfragmented box is just tall enough to fit 3 lines, and it gets fragmented in 2 equal parts, you can either put 1 line in the first and 2 in the second letting that last line overflow, and possibly overlap with subsequent content, or you can put 1.5 lines in each, slicing the second one. For that case, both approaches are bad. Depending on context, overflowing might be better than slicing, but it's not guaranteed.

However, if the unfragmented box is 3.5 lines tall or more, and the fragmentation point is 1.5 lines in, then clearly having one line in the first fragment and 2 in the second one is better: nothing is sliced, nothing overflows. Allowing that is a strict improvement.

Based on that, I'm in favor of adopting the change. It doesn't force anyone to do anything, since it's merely an allowance.

css-meeting-bot commented 4 months ago

The CSS Working Group just discussed [css-contain-2] contain:size shouldn't fragment as monolithic.

The full IRC log of that discussion <chrishtr> florian: we previously deferred this issue to contain level 2
<chrishtr> florian: idea is that size containment has two requirements: if it has size containment and it's in the context of fragmentation, then you don't want content in the box to change the size of the sum, and not change the size of each fragment
<chrishtr> florian: for the first, it's good enough for it to always have a fixed xed
<chrishtr> florian: size
<chrishtr> florian: however where you fragment and size of fragments depends on the content of this box
<chrishtr> florian: to avoid this problem we defined size containment to force a monolithic behavior
<chrishtr> florian: this suffices, but may be too restrictive
<chrishtr> florian: e.g. if you have a box that is tall enough to have 4 but have 5 and then could have two columns of 2.5, but with monolithic it'd be wasting space?
<chrishtr> florian: suggestion is to introduce a concept "quasi-monolithic" that has most but not all of the concepts of monolithic
<florian> Quasi-monolithic boxes are similar to monolithic boxes:
<florian> forced breaks within a quasi-monolithic box must be ignored by the box’s own fragmentation context
<florian> quasi-monolithic boxes should not be fragmented
<florian> if a quasi-monolithic box needs to be fragmented, the box is sliced at a point which does not depend on the box's content, only on its size and its position within its fragmentation context.
<florian> However, unlike monolithic boxes, when a quasi-monolithic box is thus broken up, its content may be fragmented and laid out normally within each of the fragments instead of being graphically sliced—although graphically slicing is also allowed.
<chrishtr> florian: the difference between quasi-monolithic and monolithic is that you can fragment within the child boxes (?)
<chrishtr> florian: browsers would gain more options for how to spread content, which might be better for printing and multicol readability
<dholbert> q+
<chrishtr> florian: should we allow this new thing in the spec? give up?
<iank_> q+
<chrishtr> dholbert: you mentioned that quasi-monolithic boxes should avoid being fragmented. wondering what that means in the situtation of a quasi-monolithic box of 1/3 page height but it just barely goes off the end, should we move the whole thing to the next page or cut it?
<chrishtr> florian: should avoid fragmenting if possible but some leeway
<chrishtr> florian: don't remember how much leeway there is
<Rossen7> ack dholbert
<chrishtr> iank_: I'd err on the side of keeping it monolithic for now.
<chrishtr> iank_: not hearing strong developer feedback
<chrishtr> iank_: in some cases Chromium is the only implementation that treats break-inside as non-monolithic. advised people to use contain: size for some cases.
<florian> q+
<chrishtr> iank_: prefer no change to spec for now
<Rossen7> ack iank_
<Rossen7> ack florian
<chrishtr> florian: if there is no implementer interest then perhaps we should just close the issue
<miriam> q+
<chrishtr> florian: but wanted to raise this because developers might want that fragmentation, and used container queries and the result was monolithic that could be bad. Maybe better to offer implementation options?
<Rossen7> ack miriam
<chrishtr> miriam: we're running into a case where people set containment explicitly, and where they set it implicitly (e.g. via container queries). for container queries the minimum containment required is desired. Maybe there is a way to address that with new modes or keywords.
<dholbert> correcting earlier notes, iank had actually said "Chromium is the only implementation to treat `break-inside:avoid` as monolithic"
dholbert commented 4 months ago
iank_: in some cases Chromium is the only implementation that treats break-inside as non-monolithic. advised people to use contain: size for some cases. [...] correcting earlier notes, iank had actually said "Chromium is the only implementation to treat `break-inside:avoid` as monolithic"

Sorry, my last-minute correction^ (attempting to answer an emote-question from @fantasai) was misguided. After the meeting ended, @bfgeek (iank) mentioned that he did actually mean non-monolithic

@bfgeek: question for you -- do you have a testcase to demonstrate what you're talking about there? (sorry for the diversion; it seems sorta-relevant since break-inside:avoid is kind-of like the behavior that @frivoal is suggesting here.)

I tested Firefox vs. Chrome on these testcases:

block: data:text/html,Hello<div style="break-inside:avoid; border: 10px solid black;font:6in monospace">A<br>B<br>C

flex: data:text/html,Hello<div style="display:flex;flex-direction:column;break-inside:avoid; border: 10px solid black;font:6in monospace"><div>A</div><div>B</div><div>C</div>

...and both Firefox and Chrome push the div to the second page, but don't slice the lines of text in half. So we're both treating it as sort-of-but-not-quite-monotonic, in the same way. :) Could you clarify what situation you're talking about where Chrome is the only engine to do the right non-monotonic thing with break-inside:avoid?