Skip to content

Implementations don't match the Flex Container Intrinsic Main Sizes algo, resulting in gratuitous differences from equivalent Grid layouts #1147

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

Closed
tabatkins opened this issue Mar 30, 2017 · 6 comments
Labels
Closed Rejected as Invalid Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. css-flexbox-1 Current Work Tracked in DoC

Comments

@tabatkins
Copy link
Member

Quoting myself from #1120:

The different between Grid and Flexbox here is in how we calculate the size of the container when some of the items have <1 flexibility, and the available space is indefinite (such as in a float).

Specifically, Grid's behavior is defined in https://drafts.csswg.org/css-grid/#algo-flex-tracks, the "If the free space is an indefinite length" substep. In your examples, it ends up computing a "used flex fraction" of 100px. In the .5/1 example, then, the tracks get sized to 50px/100px, respectively, and the grid then shrinkwraps those two tracks, being 150px wide total.

In Flexbox, the behavior is defined in https://drafts.csswg.org/css-flexbox/#intrinsic-sizes, where the "max content flex fraction"s end up computing to 0, and each item has a flex base size of 100px (due to its contents), so the flex container's size is the sum of (FBS + MCFF) for each item, or 200px wide total. If there's a .5/1 flex on the children, the sum of flexes is >1, so they then distribute that 200px with a 1:2 ratio, making the items approximately 67px/133px wide. (If the sum is <1, they get sized to an appropriate fraction of the 200px, leaving some empty space in the flexbox. The container does maintain its 200px width regardless, tho.)

I'm pretty sure Flexbox is the one with the bad behavior here. The container should pay attention to <1 flex values when finding its size, like Grid does. I'll file a bug for Flexbox instead.

Testcase showing off the differences: https://jsfiddle.net/7L9j7qjw/

@tabatkins tabatkins added the css-flexbox-1 Current Work label Mar 30, 2017
@tabatkins
Copy link
Member Author

Further investigation by @fantasai and me shows that the spec is actually correct - if you follow 9.9.1 for the cases in my linked example, they all end up with identical results to Grid.

So this looks like implementations bugs in Flexbox, across both Firefox and Chrome at least. (I can't easily test IE right now.) Maybe they didn't update impls after we fixed that section?

@dholbert @atanassov @cbiesinger

@tabatkins tabatkins changed the title Flexbox's "Flex Container Intrinsic Main Sizes" algo is gratuitously different from the equivalent Grid algo Implementations don't match the Flex Container Intrinsic Main Sizes algo, resulting in gratuitous differences from equivalent Grid layouts Mar 30, 2017
@fantasai
Copy link
Collaborator

Mozilla's bug is https://bugzilla.mozilla.org/show_bug.cgi?id=1055887 and @dholbert says he's planning to fix it.

@cbiesinger
Copy link

I'm using https://bugs.chromium.org/p/chromium/issues/detail?id=240765 for the Blink version of this bug, but yes, this is currently not fixed in Blink/Chrome.

I am concerned about the compat implications; when I find time, I need to get better statistics than I currently have for this.

@tabatkins
Copy link
Member Author

Ugh, and the specced Flexbox behavior is broken. It double-applies fractions < 1 when the total sum is < 1. :(((((

To be specific, check this case showing off Grid's behavior in a similar case. Chrome's impl happens to exactly match what the Flexbox says to do (if you translate things back to flex concepts). Note the first box - the max-content size of each item is 200px, so the .4fr calculates to 80px wide, and the .5fr to 100px wide. The grid container is thus 180px wide. Then grid layout happens normally, giving the .4fr column 40% of that space (72px) and the .5fr 50% of the space (90px), making both of them overflow (when only the .4fr one should be overflowing; the .5fr should precisely fit its children after linebreaking). In other words, the fraction gets double-applied.

The fix to this is to check if the sum of flexes is <1, and if so, renormalize the flexes to sum to 1 for the purposes of section 9.9.1. That will produce a 200px wide container, making the .4fr be 80px wide and the .5fr be 100px wide, exactly as intended; this'll then match the (expected) behavior of the .5/1.0 case, where the .5fr column is 100px wide and the 1.0 column is 200px wide.

(Alternately, do something more complicated in the layout algo to let it know that it's supposed to be snug, and we can ignore the normal behavior of <1 flex and just give it a corresponding share of the total. Both result in the same sizes for the tracks/flex items, but this makes the container smaller and snug around the items.)

@fantasai
Copy link
Collaborator

Filed Tab's issue as #1735.

@fantasai
Copy link
Collaborator

fantasai commented Sep 6, 2017

Closing this issue, with Tab's permission.

@fantasai fantasai closed this as completed Sep 6, 2017
@fantasai fantasai added Closed Rejected as Invalid Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. css-backgrounds-4 and removed css-backgrounds-4 labels Sep 6, 2017
@fantasai fantasai added this to the Published css-flexbox-1 2017-10-19 milestone Mar 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Closed Rejected as Invalid Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. css-flexbox-1 Current Work Tracked in DoC
Projects
None yet
Development

No branches or pull requests

3 participants