Open davidsgrogan opened 3 years ago
The CSS Working Group just discussed [css-flexbox] column wrap intrinsic size algorithm can make inline min-content > max-content
.
Ian mentioned this in the call but it didn't make it to the minutes:
We don't want to start shipping the new algorithm, even piecemeal in Canary, until someone has checked our tests (which validates that we understood and implemented the spec correctly). Just spot-checking a few would helpful. https://github.com/web-platform-tests/wpt/blob/master/css/css-flexbox/intrinsic-size/row-005.html has 7 cases. The 6th is annotated with some intermediate calculations, if you want to start there.
So the goal of the min-content and max-content sizes are to represent the smallest and largest sizes that the box and its contents could lay out into without triggering overflow or leaving excess space. And the intention is that the box, when set at that size, would lay out accordingly, with its contents in its fully compressed or fully unwound state, fitting its container exactly.
But for column wrap flex items, it doesn't quite work that way. If we figured out the right size for a min-content layout, for example, we'd size the flex container at that size... and then tell its items to lay out into their container. Which means they'd lay out against the available space we calculated for all the flex lines combined, rather than the min-content size of their own flex line. There's basically no good answer here.
I think the best (least nonsensical) thing we can do for the min-content size is to treat it as a single-column flex container, and just take the largest min-content contribution among the items. Which will result in overflow if the flex container has a height constraint, but at least there's some relationship between this size and fitting the contents.
For the max-content size, if we lay out each item at its max-content size, fill the columns, and then wrap a box around that, we can get a size that fits its contents exactly most of the time. The exception would be if we have percentage-sized items: they'll try to resolve against the width calculated for all the flex lines combined, and be too big. Maybe we can avoid that by suppressing percentage resolution (treating as auto
) in these cases, i.e. when the percentage is cyclic, like we do for percentage heights in block layout.
Note that this is essentially just a direct translation of what we earlier determined was the desired behavior for multicol under these situations: https://github.com/w3c/csswg-drafts/blob/main/css-sizing-4/intrinsic-sizing-notes.bs#L124 - under a min-content constraint without a set number of columns, assume it's just one column; under a max-content constraint with restrained height, "just do layout" and return the result.
Next interesting question is what about row wrap
flex containers. Do we need to do something special here as well?
Consider this case:
item {
grid-template-rows: minmax(10px, 100px);
}
<outer height="min-content">
<flex container row wrap width="tiny">
<item/>
<item/>
</flex>
</outer>
I think the two options we have here are:
column wrap
containers: take the min-content size as if it were a single row; orThe tricky part here is going to knowing when to break cyclic sizing.
Neither option is great, but they at least get a size that relates to the layout, rather than a size that's effectively random, being derived from a layout that we no longer have. (#1 gives you a 10px-tall flexbox, overflowing due to having two 10px-tall items; #2 gives you a 200px tall flexbox containing two 100px-tall items. The current spec gives you a 20px-tall flexbox, overflowing due to having two 20px-tall items, which is effectively random as far as the author is concerned.)
Thoughts?
I think the best (least nonsensical) thing we can do for the min-content size is to treat it as a single-column flex container, and just take the largest min-content contribution among the items. Which will result in overflow if the flex container has a height constraint, but at least there's some relationship between this size and fitting the contents.
Intuitively, I'd guess that most column-wrap containers DO have a height constraint. Because otherwise, why would an author use a multiline container in the first place? Single-line seems more appropriate for a column container with an indefinite height. I suppose someone would use multiline on an indefinite height container If they don't want the flex line to stretch to the full width of the container, but that strikes me as niche.
All that said, I'm happy to apply the multicol precedent to column-wrap flex containers. Hopefully there won't be that many overflow problems in practice.
For the max-content size, if we lay out each item at its max-content size, fill the columns, and then wrap a box around that, we can get a size that fits its contents exactly most of the time. The exception would be if we have percentage-sized items: they'll try to resolve against the width calculated for all the flex lines combined, and be too big. Maybe we can avoid that by suppressing percentage resolution (treating as
auto
) in these cases, i.e. when the percentage is cyclic, like we do for percentage heights in block layout.
I suppose the competing principles are (1) we want to obey whatever authors specify (i.e. not treat percent widths as auto) but (2) we don't want the container's max-content width to result in overflow. I found it so frustrating to change properties and not see any subsequent change when I was a key-mashing web developer so I'd put (1) over (2) even though (1) results in some overflow. If the author doesn't want the overflow, they'll figure out to remove the specified percent width, which is what (2) would do for them and not give them a choice to opt out.
Next interesting question is what about
row wrap
flex containers. Do we need to do something special here as well?Consider this case:
item { grid-template-rows: minmax(10px, 100px); } <outer height="min-content"> <flex container row wrap width="tiny"> <item/> <item/> </flex> </outer>
I think the two options we have here are:
- Do the same as for
column wrap
containers: take the min-content size as if it were a single row; or- Always size wrappable flex lines under a max-content constraint, never passing in a cyclic height or a min-content constraint from their container.
The tricky part here is going to knowing when to break cyclic sizing.
Neither option is great, but they at least get a size that relates to the layout, rather than a size that's effectively random, being derived from a layout that we no longer have. (#1 gives you a 10px-tall flexbox, overflowing due to having two 10px-tall items; #2 gives you a 200px tall flexbox containing two 100px-tall items. The current spec gives you a 20px-tall flexbox, overflowing due to having two 20px-tall items, which is effectively random as far as the author is concerned.)
Agree. We aren't going to implement min/max-content block sizes anytime soon so I didn't consider this issue.
I don't see why we'd deviate from #1, if #1 is what we did for multicol and will do for column wrap inline sizes. Like, what is substantially different about the row-wrap container that we would do something different? If we go with #2, would whatever reasoning we use to choose #2 also apply to column-wrap flex containers discussed above? (Sorry, I know this isn't very helpful.)
So to summarize from the background logic in https://github.com/w3c/csswg-drafts/issues/6777#issuecomment-1071211730 and @davidsgrogan's preferences expressed in https://github.com/w3c/csswg-drafts/issues/6777#issuecomment-1097318196 we're looking at:
overflow
on it's large enough to fit any given column entirely within its scrollport.Agenda+ to ask the WG if this is the direction we want to go in.
The CSS Working Group just discussed column wrap intrinsic size algorithm can make inline min-content > max-content
, and agreed to the following:
RESOLVED: Accept the proposal in the issue
Is there any reason why this hasn't been resolved? It appears the necessary edits were made in 2022 in https://github.com/w3c/csswg-drafts/commit/5630e7b064addc6f2f9f57e68935e3cb3e778b65.
https://drafts.csswg.org/css-flexbox/#intrinsic-cross-sizes
Flex's intrinsic cross size algorithm can lead to inline
min-content > max-content
for a column-wrap container.In the example below, the two items are identical. They each have min/max-content contribution of 75px,100px.
To determine container's
max-content
size, we lay out each item with available width 100px[1]. The items' resulting heights are each 50px, so we can fit both of them in a single flex line of width 100px. So container'smax-content
size is 100px.To determine container's
min-content
size, we lay out each item with available width 75px[1]. Laying out the first item with available width 75px gives the item a height of 100px. The container is 100px tall so this item fills an entire flex line. item2 is forced into a second flex line. The width of each flex line is 75px, so container'smin-content
size is 150px.So
min-content size 150px > max-content size 100px
, which seems bad.The problem is exacerbated if the container has
column-gap > 0
.Strawperson possible solutions:
min-content
ormax-content
constraint.min-content = max-content
for all column wrap containersmax-content
bymin-content
. I.e.final max-content = max(min-content, max-content)
[1] From the spec link above:
/cc @bfgeek