Skip to content
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

[css-flexbox] flexbox spec isn't interoperable w/ existing implementations, RE flex-basis resolution for table wrapper box flex-items #2604

Closed
dholbert opened this issue Apr 23, 2018 · 8 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

@dholbert
Copy link
Member

I recently implemented the keyword flex-basis:content, and implemented the spec behavior on treating used flex-basis:content as max-content. (This includes treating flex-basis:auto;[main-size-property]:auto as max-content.)

However, this creates a bit of a problem for an annoying edge-case -- table wrapper boxes as flex items.

Table wrapper boxes do not receive the author's specified width/height nor flex-basis value[1], so they always necessarily have flex-basis:auto;[main-size-property]:auto, which means they always have a used flex basis of content. This means (per the current spec) they should always resolve their flex base size to their max-content size.

But I've found that's problematic for scenarios like this:

<flexbox style="width:300px">
  <table style="width:100%"></table>
</flexbox>

Right now, Firefox 59/Edge/Chrome all render content like that ^^^ with the table being 300px wide. But with my attempt at implementing the current spec text, Firefox Nightly ends up resolving the flex base size by sizing the table-wrapper as max-content, and that means we can't resolve the 100% width on its child box (the table box) because by definition max-content sizing is independent of the surroundings; and so the 100% ends up getting treated as auto and we end up collapsing the table to its actual content-size, which might be 0 instead of 300px, depending on what it actually contains. So, we end up with a flex base size of 0px (or whatever the content size is), rather than 300px. This is what really happened in Firefox Nightly with my changes, and it caused problems in a real website (a French flight booking site).

The spec needs to say what should happen here -- should table-wrapper-box flex items really always get a flex base size of their max-content size? (which is what the spec calls for, but no official UA release implements, aside from current Firefox Nightly I think) Or should they do something subtler, e.g. maybe using the fit-content size in this scenario? (which, unlike max-content, is allowed to take the available space into consideration) Or should they do something else?

[1] The spec says that order and align-self apply to the table wrapper box, but "like width and height, the flex longhands apply to the table box..." (And then there's some special case about how table boxes should work with flex layout, but it seems to me that this special-case text is all post-flex-base-size resolution.)

@Loirooriol
Copy link
Contributor

we can't resolve the 100% width on its child box (the table box) because by definition max-content sizing is independent of the surroundings

Isn't this bypassed by https://www.w3.org/TR/CSS21/tables.html#model and https://drafts.csswg.org/css-tables-3/#ref-for-table-wrapper-box?

Percentages on 'width' and 'height' on the table are relative to the table wrapper box's containing block, not the table wrapper box itself.

Percentages which would depend on the width and height on the table-wrapper box’s size are relative to the table-wrapper box’s containing block instead, not the table-wrapper box itself.

@dholbert
Copy link
Member Author

No, it's not bypassed by that. max-content sizing of a box (the table-wrapper box in this case) does not get to benefit from any information about the ancestors -- that's part of the principle of what max-content sizing represents.

@dholbert
Copy link
Member Author

dholbert commented Apr 23, 2018

For a normal flex item (e.g. a block) that has width:100% (with default flex-basis, in a horizontal flex container with a definite size, this isn't a problem, because the flex item's max-content size doesn't come into play in the algorithm. In that scenario with a block flex item, the item's used flex-basis is 100%, which we are allowed to resolve per flexbox spec section 9.2 step 3.A:

If the item has a definite used flex basis, that’s the flex base size."

(The business about max-content size is a bit further down, in a case that we don't fall into for this block scenario -- see below.)

In contrast, for a flex item that is a table-wrapper-box (the scenario I care about here): the item's flex-basis and width will both necessarily be auto (because authors can't directly style those properties on the table wrapper box), which means we have a used flex-basis of content (per definition of flex-basis:auto, which means we do fall down to section 9.2 step 3.E, which says:

size the item into the available space using its used flex basis in place of its main size, treating a value of content as max-content

So we're effectively trying to resolve the size of a table-wrapper-box that has "width:max-content", and by definition, that max-content width isn't influenced by the containing block's size (and so the percent on the child can't resolve against it, for the benefit of computing the used flex basis). But in practice, all browsers that I've tested (besides Firefox Nightly from the past few days) do let the percent be resolved and let it influence the flex base size (and hence the actual flex item size) -- testcase: https://jsfiddle.net/x1te0pra/

(Both spec quotes here are from https://drafts.csswg.org/css-flexbox/#algo-main-item )

Suggestion: Maybe we need a special case for table wrapper boxes in section 9.2 step 3.E, where we treat content as fit-content for table wrapper boxes? (not as max-content) That's effectively what Firefox was doing up until recent nightlies, and that would allow percentages on the table-box to be resolved & to influence the flex base size.

@Loirooriol
Copy link
Contributor

I'm not convinced, since percentages on the table box are not relative to the table wrapper box, they are not cyclic percentages (assuming the table wrapper box's containing block has a definite width). Therefore I don't think the percentage should be treated as auto when sizing the table wrapper box with max-content.

by definition, that max-content width isn't influenced by the containing block's size

Does the definition actually say this? Not sure if I'm looking at the wrong definition. I think your statement is almost always true, but not for table wrapper boxes.

@dholbert
Copy link
Member Author

by definition, that max-content width isn't influenced by the containing block's size

Does the definition actually say this?

I'm looking at this definition:

The max-content size of a box in each axis is the size it would have
if it was a float given an auto size in that axis (and no minimum or
maximum size in that axis), and if its containing block was
infinitely-sized in that axis.

https://drafts.csswg.org/css-sizing-3/#intrinsic-sizes

So notably: the actual size of the containing block is unavailable, because it's determined in a hypothetical "if it's containing block was infinitely-sized in that axis" scenario.

@dholbert
Copy link
Member Author

(Having said that - in practice, the spec's technique there isn't quite right for table wrapper boxes. If I follow the spec's hypothetical steps there -- floating the table-wrapper in an infinitely-sized [or just extremely-large] containing block -- I get the following, with the table itself being extremely large:
https://jsfiddle.net/yt6c9v3m/
I think the spec really wants to say "if its containing block had an indefinite/unconstrained size in that axis".)

@fantasai fantasai added the css-flexbox-1 Current Work label Apr 25, 2018
@fantasai
Copy link
Collaborator

fantasai commented May 1, 2018

No, it's not bypassed by that. max-content sizing of a box (the table-wrapper box in this case) does not get to benefit from any information about the ancestors -- that's part of the principle of what max-content sizing represents.

It is, though. The table wrapper box is there mainly to hold the table and its caption together. Its sizing is determined by the size of those items rather than by any sizing properties set on it.

The Flexbox spec says

In the case of flex items with display: table, the table wrapper box becomes the flex item, and the order and align-self properties apply to it. The contents of any caption boxes contribute to the calculation of the table wrapper box’s min-content and max-content sizes. However, like width and height, the flex longhands apply to the table box as follows: the flex item’s final size is calculated by performing layout as if the distance between the table wrapper box’s edges and the table box’s content edges were all part of the table box’s border+padding area, and the table box were the flex item.

the flex longhands apply to the table box as follows ... and the table box were the flex item”.

What the spec is trying to say is that the table box is what gets flexed by the flex properties, just like the table box is what gets sized by the sizing properties. We have to account for the captions somehow, though, so we're ignoring them and the table wrapper box, except insofar as the captions take up space. And as @Loirooriol says, per CSS2.1 the percentage resolves on the table exactly as if the wrapper box wasn't there.

The width of the table wrapper box is the border-edge width of the table box inside it, as described by section 17.5.2. Percentages on 'width' and 'height' on the table are relative to the table wrapper box's containing block, not the table wrapper box itself.

Overall I think this issue is invalid--as in the spec says it should behave the way you want it to behave--but I'm not sure where you're getting confused or how to fix it.

  • CSS2.1 says that the table wrapper box is ignored for calculating percentages--they are resolved against the table wrapper box’s parent.
  • Flexbox says that the table wrapper box does not participate in flex sizing: it is bypassed so that flex sizing calculations are applied to the table grid box, with some accounting for the space taken up by the captions. (This is consistent with CSS2.1's point about percentage calculations.)
  • CSS2.1 says that the table wrapper box’s width is affixed to the final width of the table grid box. (So it being ignored for sizing is fine, its size gets calculated exceptionally from the size of the table grid box, which is sized via flex layout in its place. It doesn't get sized independently.)

@dholbert
Copy link
Member Author

dholbert commented Jun 20, 2018

Thanks for the response (and sorry for the long response time on my part).

I think you're right that the spec basically covers this; I was perhaps reading too much into the first sentence of the paragraph you quoted ("the table wrapper box becomes the flex item"), and not reading enough into the last sentence ("layout as if...the table box were the flex item").

That last sentence is a bit hand-wavy, but in retrospect I guess it's a pretty strong requirement (and it's not what Firefox/Edge seem to do now, FWIW ( testcase here ) but it seems like a reasonable thing to do).

So, bottom line, I think the direct answer to my original concern here is:

  • Yes, the used flex-basis on the table-wrapper box is indeed always "content"...
  • ...BUT that doesn't matter, because the above-quoted spec paragraph's last sentence says to perform layout as if the table box were the flex item (even though it's technically not).
  • So: in that spirit, we should be looking at the used flex-basis on the table box (which is not content in my example) and using that to determine the flex base size, resolve flexible lengths, etc.

So I think we're OK here. Incidentally, https://bugzilla.mozilla.org/show_bug.cgi?id=1456224 is filed on bringing Firefox closer to what the spec requires on this point.

@atanassov atanassov added Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. and removed Commenter Response Pending labels Aug 20, 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

4 participants