Skip to content

[css-flexbox] Multi-line column flexbox fragmentation #6855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
alisonmaher opened this issue Dec 3, 2021 · 8 comments
Open

[css-flexbox] Multi-line column flexbox fragmentation #6855

alisonmaher opened this issue Dec 3, 2021 · 8 comments

Comments

@alisonmaher
Copy link
Collaborator

As noted in the sample algorithm for multi-line column flex containers:

If a flex item does not entirely fit on a single page, it will not be paginated in multi-line column flex containers.

Why are items in a multi-line column flex container suggested to be treated as monolithic while the other algorithms do not? For example, shouldn't a fragmented multi-line column flex container with one column behave the same as a fragmented single-line column flex container?

The flex fragmentation spec also mentions:

When a multi-line column flex container breaks, each fragment has its own "stack" of flex lines, just like each fragment of a multi-column container has its own row of column boxes.

To me, this almost implies that a multi-line column flex container will act as a fragmentation context (expect for the fact that items are considered monolithic, as mentioned above). Does it make sense to do the same thing here as a nested multi-column? If we were to instead fragment each flexbox column independently, when stitched back together, the columns would match more closely to the unfragmented result.

Note: neither Gecko or Chromium's implementations of multi-line column flex fragmentation are currently following either of these points in the spec.

cc @mstensho @bfgeek

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-flexbox] Multi-line column flexbox fragmentation, and agreed to the following:

  • RESOLVED: Treat items as not monolithic
  • RESOLVED: update fragmentation rules to flexbox to handle multiline independently
The full IRC log of that discussion <dael> Topic: [css-flexbox] Multi-line column flexbox fragmentation
<dael> github: https://github.com//issues/6855
<dael> alisonmaher: This issue is how to handle frag for multi line column. A couple questions
<dael> alisonmaher: First is around the spec rec to treat items as monolithic. Curious reasona nd if we should remove b/c otherwise items in a single line could frag differently than a 1 line multi line
<TabAtkins> q+
<dael> alisonmaher: Also, each element has it's own stack. Implies multi-line column flex has it's own context except items are monolithic. Doesn't make sense. If we frag independantly the result would be closer to unfragmented. Firefox doesn't match for either of these
<dael> alisonmaher: Prop is update spec to match FF for frag multiline column
<dael> alisonmaher: May have to reconsider break-before and -after
<dael> alisonmaher: Curious about reasons to keep spec text as is
<Rossen_> ack TabAtkins
<dael> TabAtkins: First, alisonmaher , this entire chapter was a best guess set up and we're happy to change to match impl or good results.
<dael> TabAtkins: What you're saying makes sense. Pending more detailed review as I write this seems plausable
<Rossen_> ack fantasai
<dael> fantasai: What TabAtkins said, chapter was a best guess. Multiline column felxbox was the weirdest. Written the way it was b/c not sure what you're suggesting is possible. If it is possible to shuffle across page break, it makes more sense.
<dael> fantasai: As to if we should make any changes to this, we should try and match both good behavior and implementations. I think these changes make sense
<Rossen_> q?
<dael> Rossen_: Other opinions? fwiw I remember some reasoning behind monolithic items it was b/c simplier and we were waiting for an implementation and here we are
<dael> Rossen_: alisonmaher can you summerize
<dael> alisonmaher: Update flexbox spec to frag multiline columns independantly and make items not monolithic
<dael> robObj to not monolithic?
<dael> RESOLVED: Treat items as not monolithic
<dael> Rossen_: Obj to update fragmenetation rules to flexbox to handle multiline independent
<dael> RESOLVED: update fragmentation rules to flexbox to handle multiline independently

@fantasai
Copy link
Collaborator

@tabatkins and I were looking into how to make these edits, and on further thought aren't convinced that what's described in the minutes is actually desirable.

Here's a testcase showing off a multiline column flexbox being fragmented by a multicol. The desired behavior is, of course, that content is properly fragmented and not overflowing its container.

Chrome behavior (content is not properly fragmented; it instead just visually slices):
Each flex item is laid out normally, as one piece, then visually sliced if it splits across a column.

Firefox behavior (content properly fragments, but overlaps because the flex item fragments aren't resized to accommodate their contents, which therefore overflow):
The flex items lay out normally, then the item itself is visually sliced, but its contents are properly fragmented, so lines of text that would half-overflow the column are moved to the second item fragment, taking up more space than is available.

Properly breaking a multiline column flex container in the way described in the minutes requires laying out each line across all of the fragmentainers one by one, so that the increase in size due to fragmentation is accounted for during that line's layout. This is possible to do, but is fairly complicated and requires passing layout information back and forth across fragmentainers. If we want to do that while honoring alignment and flexing across fragments, that requires cycling the layout while we try various combinations of sizing/positioning and fragmentation breaks. Is this what we want specced? Is this something we believe can be implemented properly?

(Fwiw, the approach outlined in the spec follows the multi-col paradigm of laying out content in "rows" of columns, each fit into the "page". This has the disadvantage of laying out the contents in a different visual order than when the container is not fragmented, but has the advantage of the first items in the container being visible on the first page, and of laying out the entire contents of each fragmentainer before moving on to the next.)

@tabatkins
Copy link
Member

One bit that can influence the desired behavior is whether the flexbox is being used as a content layout device (where reflowing differently when fragmented is fine and even desirable) or a page layout device (where "lay it out infinitely, then slice it with a minimum of change" is more desirable).

While the other three flex-flow values can be legitimately used for both cases (in particular, there's some clever tricks that use row wrap for better control of wrapping across layout breakpoints), I think column wrap is exclusively, or at least very heavily tilted toward, the content-layout use-case. I don't recall ever seeing any tips on using column wrap for clever page layouts; it's, as far as I can tell, solely useful for laying out chunks of content in an area. We should thus tilt our reasoning towards that case, and the current spec handles it better imo.

@alisonmaher
Copy link
Collaborator Author

alisonmaher commented Apr 19, 2022

@fantasai @tabatkins the latest flex fragmentation implementation in Chromium hasn't shipped yet, which is why you are seeing this behavior (although it likely will be turned on soon https://chromium-review.googlesource.com/c/chromium/src/+/3594004).

With --enable-blink-features=LayoutNGFlexFragmentation, this is what that test case looks like in Chromium:
flex-frag-example

We do have to store some info (such as item offsets) between fragmentainers to get this to work, but we don't pass info back and forth (we only pass it in the forward direction). We will adjust offsets and the intrinsic block size of the container if things are shifted as a result of fragmentation. But we never go back to a fragmentainer that has already completed layout.

To avoid circularities, we may break certain flex-specific rules as a result of fragmentation (ex. we may lay out an item past the end of the container when it is end-aligned if one of the items had break that caused things to get shifted down). This matches how we are currently handling flex row fragmentation (and grid fragmentation) in Chromium.

I suppose we can leave the spec as-is if you both feel strongly, but I suspect we won't plan to update the implementation in Chromium to match (unless of course we receive bugs around this). cc: @bfgeek in case you feel differently.

@tabatkins
Copy link
Member

Thanks for the update with the new flag's results!

I'm curious about the details of that, tho - it appears to indeed be laying out the items monolithically? For example, in the first column there should be enough space to lay out the first line of text in the second item. Can you elaborate on what's going on there?

@alisonmaher
Copy link
Collaborator Author

That behavior isn't flex specific. It looks like this is a result of orphan handling. If you set orphans: 1 you'll get the following behavior instead:

orphans-1

So we aren't treating the items as monolithic in this case. It just happened to look like it in that particular example.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-flexbox] Multi-line column flexbox fragmentation, and agreed to the following:

  • RESOLVED: not required to re-wrap from column flexboxes in order to avoid overflow
The full IRC log of that discussion <dael> Topic: [css-flexbox] Multi-line column flexbox fragmentation
<dael> github: https://github.com//issues/6855
<dael> alisonmaher: I think fantasai put this on the agenda so could do a better job summerizing
<dael> fantasai: We were gonna spec the behavior but had questions about exactly what to spec in terms of frag influencing sizes of boxes
<Rossen_> example being described - https://github.com//issues/6855#issuecomment-1102928864
<dael> fantasai: Let's say you have 4 boxes inside container and splits across pages. Point it frag can cause flex items to get taller which changes alignment and space distribution
<dael> fantasai: ideally no overflow. Author doesn't expect overflow b/c said to wrap
<dael> fantasai: Question is do we want to put and algo that requires passing info and poss re-wraping or do we want to have overflow? What are the consiquences of frag that we'll accept
<Rossen_> q?
<dael> iank_: I can touch on this for grid since has similar problems
<dael> iank_: Grid will run the full layout algo, get where everything is and size. Then it will perform fragmentation step
<dael> iank_: There's just small adjustments when it makes sense. If a grid item is auto-height then we will grow out that item and shift things below it down. Try not to cause overlap. Similarly will stretch other grid items
<dael> iank_: When looking atflex wanted to follow similar. When you try and rerun is a problem.Similar where you run algo once and do fragmentation fixups seems good solution
<dael> fantasai: Diff between grid and flexbox, grid you placed the items in the rows. If the author has overconstrainded then you overflow, but if it will fit there is no problem. Flexbox you run for a column, see what fits, and then wrap. if you grow b/c the stacking you will overflow the box
<dael> iank_: Unless box is auto height
<dael> fantasai: IN which case you wouldn't wrap
<dael> iank_: Right. I think this is relatively rare for flexbox columns. Fundamentally issue with frag is in order to frag you need to place in fragmentainer. Codependency on position and size
<dael> iank_: I don't think it's bad...most of the time if opt for new column there may be space under. Most of the time expansion is small. Don't know if it's much of a problem in practical
<dael> fantasai: Could be an image. Point is are we going to overflow when frag and is that acceptable
<dael> iank_: I think cases would be rare and it's acceptable
<dael> iank_: alisonmaher did you want to add anything?
<dael> alisonmaher: Not much to add. Agree. note for out of flow frag we'd overflow or go past the end if end aligned. Doing similar is not too big a problem
<dael> fantasai: I don't think overflow bottom aligned stuff is great idea. Authors bottom align a lot and don't expect overflow when print. case with columns and wrapping you don't have a choice, but for alignment there's all that space you could have used to fit the item. Overflow doesn't make sense
<dael> iank_: Alignment topic has same problem in grid. If you center or bottom align have potential to overflow. if you don't do that algo becomes impossible to impl
<dael> iank_: In order to know how large something is you have to place, if you change placement need to resize
<dael> fantasai: Not impossible, but really unpleasent if layout from top to bottom. Could do from bottom to top, but I don't expect that
<dael> fantasai: More important to align correctly or not have overflow when print? Or a way to not have either problem
<dael> Rossen_: It's important to make sure we have a stable algo so we don't run into performance clips that would be terrible when not printing
<dael> Rossen_: With infinate time we can compute beuatiful layouts, but want to make sure this is close to linear
<dael> fantasai: I don't think linearity is problem there. I can accept fxied height column wrapped fragmenting is rare. I don't think that is true for alignment in general. I don't think we should overflow content when printing things bottom aligned. More complicated and simplier ways to avoid, but shouldn't cause overflow on layouts that should never be overflowing in the common cases
<dael> fantasai: But that is sep issue
<dael> iank_: Yeah. Happy to discuss more
<dael> iank_: When I experimented with grid only happens when item itself fragments. mitegation is something like break inside a void
<dael> fantasai: People do entire page layouts in grid, though. A lot of grid layout where you don't want to break, but a bunch other with float that expects to break across multiple pages
<dael> Rossen_: How do we want to move forward?
<fantasai> s/float/flow content/
<dael> florian: Seems to me we have multiple similar but distinct situations here
<dael> florian: fantasai argument makes sense, but there is question of implcomplexity. Are there subcases in here where we can decide or do we need it all in one go?
<dael> iank_: Fragmentation has codependency on position. For block and table always know position before layout. When introduce alignment in grid and flex sometimes have this not typically
<dael> iank_: When you position it effects size, sometimes in large and unpredictable ways. Moving one px might be drastic b/c have a 100px monolyth in it. Without testing every px can't know size at a position
<dael> iank_: I'd be against saying test every position, but that's the impl complexity
<dael> fantasai: You don't have to do that to prevent overflow. You could say that if it frag such that it will overflow, you don't align but instead start-align so it fits.
<dael> fantasai: If you want lots of work but great you can frag bottom-aligned containers separately, but wouldn't recommend
<dael> iank_: Can't do if content has overflowing content inside
<dael> iank_: I think this is slightly separate from the issue
<dael> fantasai: Yeah. For case of column wrapping stuff I think it is rare enough that if it overflows and looks like a mess the user will be unhappy but it's rare. If we want to cause overflow I'm willing to accept for this one. not willing to accept for normal alignment and common things
<florian> +1
<dael> Rossen_: So, iank_ or alisonmaher what's your position? Continue thinking more?
<dael> iank_: For alignment should open separate issue. This is complicated stuff. We should discuss separately
<dael> Rossen_: If we open the alignment issue, what can we resolve for this issue?
<fantasai> s/common things/common things. It's more important to avoid overflow than to honor alignment/
<dael> iank_: I don't think we need to resolve on anything. Maybe wrong
<dael> Rossen_: fantasai anything to keep this issue open?
<dael> fantasai: Need to resolve that fragmentation algo for column-wrap flex containers can cause items to overflow even if would not have overflowed otherwise
<dael> Rossen_: I think that's an easy resolution to take
<dael> fantasai: Specifically to avoid re-wrapping the columns
<dael> fantasai: Not required to re-wrap the columns
<dael> fantasai: to avoid overflow
<dael> plinss: Can live with that. but I don't want spec lang to say you must overflow. if you can do better want to make sure you can
<fantasai> plinss++
<dael> Rossen_: Sure. Can resolve as may overflow
<dael> plinss: Generally reluctant to have attitiude that fragmentation is hard so let's do what's easy. Have been doing that for 25 years and frag has been broken. Rare is not justification to do wrong
<dael> Rossen_: Agree, but think you're overstretching. Everyone is trying to make frag as good as possible. Edge cases we'll do in performant way
<dael> plinss: Saying people can do simple because rare. Not happy with that
<dael> iank_: Yeah. We're focusing a lot of time to have a high quality baseline engine. Number of bug reports for fragmentation is very high so we see it's important use case
<dael> plinss: I accept that and accept that impl is hard and bugs need to be prioritize. Impl won't always get it right. Want to be careful not to spec bad behavior
<dael> Rossen_: Fair. I think prop resolution here for the described case it should be may overflow
<dael> florian: We've had other cases where spec may where noone felt they could do good thing at the time and then we could eventually remove it. Let's keep the door open
<dael> Rossen_: And I think great work happening across the board on fragmentation so hopeful we'll get there
<dael> fantasai: Prop: not required to re-wrap from column flexboxes in order to avoid overflow
<dael> Rossen_: Additional comments?
<dael> Rossen_: Objections?
<dael> RESOLVED: not required to re-wrap from column flexboxes in order to avoid overflow
<dael> Rossen_: Let's open new issue for alignment case

@fantasai
Copy link
Collaborator

fantasai commented Jan 11, 2025

Adjusted pagination testcase for future reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants