-
Notifications
You must be signed in to change notification settings - Fork 682
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-grid][css-contain] Clarify that contain:size
affects track sizing
#4931
Comments
(I've filed a Chromium bug.) |
I don't believe that is the intent of the containment specification. From the spec:
This is effectively just an early out when computing the intrinsic sizes for an element.
Any layout algorithm should not then change its behaviour after the above step. E.g. these two cases should render the same: <div style="display:inline-grid; contain:size;">
<item style="background:red">Hello Kitty</item>
</div> <div style="display:inline-grid; width: 0px;">
<item style="background:red">Hello Kitty</item>
</div> |
Chromium and Firefox are not interoperable in these cases: <div style="display: inline-grid; grid-auto-columns: 50px; height: 50px; contain: size; border: 5px solid">
<div style="background: yellow"></div>
</div> <div style="display: inline-grid; grid-template-columns: 50px; height: 50px; contain: size; border: 5px solid"></div> In Chromium, the content area of the grid container is 50px wide, in Firefox it's 0px. @MatsPalmgren, in https://bugzilla.mozilla.org/show_bug.cgi?id=1488878#c1 you say that what you want to implement is
This seems what Chromium is doing, i.e. step 1 can create implicit tracks, tracks may end up being bigger than 0px in step 2, and this affects the size of the grid container in step 3. However, according to the CSS Grid spec, once we know the size of the grid container, it's laid out again "for real". So there are more steps:
Then I'm not sure why you think that the tracks should be 0px in your example. Do you want to avoid laying the grid again if there is size containment? |
The "including when computing its intrinsic size" (my emphasis) seems to imply that it affects more size calculations than just the intrinsic size of the box itself. I don't see anything in the spec that supports the idea that it only affects the intrinsic box size.
Did you forget the Anyway, the Containment spec already says that "this does not necessarily make the element zero-sized: properties set on the element itself, such as the columns property or the grid property, continue to be taken into account.". I read "taken into account" there as "run the TSA pretending that the grid container has no items", which is what I suggested in the OP. I don't think there is a way to take the grid properties into account in any other way. |
My understanding is the same as @bfgeek and @Loirooriol here. The "inculding intrinsic size" bit means that if the layout of any parent of the size-contained element depends in some way on the intrinsic size of that size-contained element, then that input to its layout is the same as if that size-contained element was empty. For instance, the size of a grid row depends on the intrinsic sizes of the elements in that row. Say you have a column which is sized to min-content, we look at the intrinsic min content size of the elements in the column, pick the largest, size the column that way, and then do the actual layout of the grid items in that column at that width. During that phase, if any of the grid items have size containment, they'll be treated as empty for the purpose of figuring out their min-content size. However, setting size-containment on the grid itself would not affect the intrinsic size calculation of the grid items.
No, it means that it's both the size of the box in actual layout, and the intrinsic size of the box if requested by its parent, that are calculated as if the box were empty. Not that other unspecified operations (such as track sizing) also treat it as empty. The spec tries to be explicit that once you've done this sizing step, everything else runs normally, with the following statement:
For the purpose of finding how big the grid is, yes. Hence the grid in your example being sized to At least:
That said, if it is not clear (which seems to be the case), the spec should certainly at least be clarified. If we have agreement that the behavior suggested here would be more useful, I suspect we could switch to that, but it's not clear to me that it is.
Yeah, in that case, Chromium is right and Firefox is wrong. That is exactly what the note in the spec is about:
|
WPT has (at least) two tests for that, which Firefox fails: Interestingly, Firefox does pass the corresponding multicol tests: |
This is a fundamental misunderstanding of how Grid layout works. Track sizing isn't "other unspecified operations" unrelated to a grid container's size. It's literally the way you calculate its content-box size, per spec: "The max-content size (min-content size) of a grid container is the sum of the grid container’s track sizes (including gutters) in the appropriate axis, when the grid is sized under a max-content constraint (min-content constraint)." So suggesting that size-containment doesn't affect track sizing makes no sense because if it doesn't then it can't affect the grid container's size either. To be concrete, here's how Gecko reports "the intrinsic size of the box if requested by its parent". I've highlighted the three salient steps there:
OK, so it seems what you're trying to say then is that
I'm guessing "how big the grid is" means "what the content-box size of the grid container is". (please try to use precise terms that are defined in specs or we're going to talk past each other).
Doing what you suggest means that we have to run the TSA twice: once without items to determine the grid container's content-box size and once with items to determine the track sizes to use for layout of the children. Always running the TSA without items, as I suggested in the OP, is an optimization (and a lot simpler to implement since running it once is what we're currently doing).
Right, but the way you "take the grid property into account" is to run the TSA. So again, there is no other way to implement this but to run the TSA without items (at least under a min-/max-content constraint) and use the track sizes that falls out. If you're thinking of something else then please point to spec text that defines that alternative algorithm. I can live with doing it twice I guess, if you all think it's important that intrinsic track sizes should be sized normally before laying out the children. |
@MatsPalmgren Can you clarify what's your proposal if you don't want to run the TSA without items when sizing the grid container under a min/max-content constraint, and then run the TSA with items when laying it out for real? In your first comment you say that the track size should be 0, seemingly implying that you only want to run the TSA without items, never with items. In your last comment you seem to mean that you want to ignore So not sure I understand your proposal. |
Right, that's option A.
No, I never said <div style="display:inline-grid; contain:size; grid:auto 100px / auto 200px">
<item><div style="width:300px; height:300px"></div></item>
</div> with option A:
I've described two different options (so far). I hope they are clear now. BTW, I'm assuming above that the grid item placement step in the Grid layout algorithm always occurs, also for The "treated as having no contents" implies that implicit tracks should not be created (since there are no items if we treat it as having no contents), for example: <div style="display:inline-grid; contain:size; grid-auto-rows:100px; grid-auto-columns:100px">
<item></item>
</div> Chrome makes the grid container content-box size So the spec needs to say explicitly which parts of Grid layout are supposed to be run with/without items, unless it means all of them. I don't have a strong opinion on which option to choose. Option B seems to be close to what Chrome is currently doing and that seems to be the behavior you guys prefer, so that's fine with me. It needs to be clearly specified how it's actually supposed to work though, because the current spec text suggests something completely different. |
Also, the part about honoring I assume honoring |
The definition of intrinsic sizes is explicitly about the min-content size and max-content size, not about track sizes or any other sizable aspect of an box (grid track sizes, multicol column sizes, etc). So by my reading (and by my intent when writing it), the spec calls for finding out the min-content width and height and max-content width and height (if you ever need them) and the width and height of the element as if it were empty, and once you've done that, you do full layout using these sizes. Yes, it does imply that you run the grid track sizing algorithm twice, once with empty tracks (for sizing purposes) and once with actual content (when doing the layout). A possible implementation strategy could be to have a specialized (and simpler/faster) implementation of the track sizing algo that only does track-sizing of an empty grid. I'm still not understanding how the spec can be seen as ambiguous about that. For example, you said:
However, to get to this interpretation, you need to ignore the "when calculating …" part of the sentence. When you calculate the size of the box, you treat it as having no content, and therefore do not reserve room for any implicit track. When laying out the grid into that size, you do the full grid layout, with its content, including sizing the tracks correctly, and creating implicit tracks as necessary. Even if it is not ambiguous, it may still be a bad idea. I don't think it is a bad idea, but we can discuss that.
Anyway, If I understand correctly, you're not necessarily advocating for "option A", merely saying that the spec could be read that way, and want it to be clearer on whether it means A or B. I remain unconvinced that it can be read to mean option A, but nonetheless, if you have a suggestion of better phrasing to gets unambiguously to option B, it's always better to be clearer. By the way, the reason why the grid text is in a note is that no additional normative requirement is meant on grid, and this is just an illustration/reminder of how the preceding normative text is meant to be applied to grid. I believe that option A would be special rules for grid, and would need to be normative. |
The grid area would be 0x0, yes, but wouldn't the item be bigger due to the automatic minimum size? Or would it not apply since we would kind of be treating the
@frivoal You don't? So Chromium is wrong? To summarize this issue, below I list the possibly unclear questions about the interaction of grid and size containment. When sizing a grid container with size containment under a min/max-content constraint,
When laying out the grid container with size containment into that size,
|
I think so:
So, answers to your numbered questions are:
No, that would defeat the point of using size containment.
Yes. We could switch to no without defeating the point of using size containment, but that would result in a less useful layout.
Agreed.
Agreed
Agreed. We could switch to no without defeating the point of using size containment, but that would result in a less useful layout.
Yes. We could switch to no without defeating the point of using size containment, but that would result in a less useful layout. Also, if authors have a layout which would be resilient to that and want the extra optimization opportunities, they can apply size containment to the grid items.
I don't think 6 should be negative, so ¯\_(ツ)_/¯ |
But to calculate the intrinsic size of a grid container you need to calculate its track sizes first, since the Grid spec literally says that its intrinsic size is derived from those. Hence the question of how they should be calculated for
But the contain:size spec says that it should be treated as empty in more cases than just for intrinsic sizing though: If you meant that it should only affect the intrinsic size of the container's box then you need to change it to "When calculating the intrinsic size of the containing box, it must be treated as having no contents." so that it excludes the "when laying out the grid into that size" phase (to use your phrasing). The ambiguity with Grid layout though is that the track sizes are calculated again during the layout phase and that part of layout is considered an intrinsic sizing step (not the container's intrinsic size, but the track sizes). So I think the Containment spec needs to make it clear that that step is excluded from the "treat the container as empty" condition.
Correct, I claim that the
Right, but the problem is that, for a few of the possible interpretations of the spec, it's not just clarifying the preceding text. If we go for the "it should be treated as empty so implicit tracks aren't created" option then yes, in that case it's only a clarifying note. Otherwise, it's not just clarifying but instead modifies/contradicts the preceding text and thus shouldn't be in a note. |
I think I agree with your answers to @Loirooriol's questions but let me clarify one point to avoid any misunderstanding:
This is the wrong way to see it IMO. We should run the placement algorithm, and all other algorithms for that matter, it's just that when we treat the container as empty then we have zero items and thus we don't create any implicit tracks. IOW, when calculating the container's intrinsic size for So the spec changes I would suggest are:
(3 is needed to clarify that the Resolve Intrinsic Track Sizes step for Grid should not treat the container as empty during layout. (Perhaps there are other cases (multicol? flexbox?) where this also matters, I haven't checked.)) EDIT: let's call this option C, since it's different from option A and B which I presented in #4931 (comment). |
BTW, is "containing box" really a good term to use? Isn't "container's box" clearer? Or perhaps "principal box" would be better since it's an already established term. |
@frivoal Well, but the spec says "When calculating the size of the containing box". The Grid Item Placement Algorithm is not part of the Grid Sizing Algorithm, it's a previous step. So if the size containment is supposed to apply not only during sizing but also during previous steps that can affect sizing, then the spec should probably clarify it.
It seems to me this would be more like style containment rather than size containment. My understanding is that size containment is only supposed to prevent the intrinsic size of an element from depending on the size of the contents. But in this case, the existence of implicit tracks wouldn't depend on the layout of the children, only on their computed style. So I'm not opposed to avoid creating implicit tracks with size containment, but I'm not convinced that's necessary.
@MatsPalmgren But in practice it doesn't matter, right? The placement algorithm places items, if it behaves as having no contents then there are no items to place and the placement algorithm is no-op. |
Sure. That's a reasonable clarification.
This too seems like a useful clarification.
That would not work: If the size-contained grid is inside of a absolutely positioned element, or inside of a float which is itself inside a zero-width div, then when we try to figure out the size of the abspos or of the div, we look at the intrinsic size of its content (the size-positioned grid): the max-content size in the case of the abspos, the min-content size in the case of the float in a zero-width container. This is correctly captured by your phrasing (and also I believe by the one currently in the spec). However, the effect is not limited to this, and your suggested edit drops the other part: If a size-contained grid is an ordinary block-level child of an ordinary div, the grid must still be sized as if it were empty, then laid out in that size. For a grid with no gap, fixed-sized track, etc, than would mean a width equal to that of its block container, and a height of 0. This is not calculating the intrinsic size of the grid. It is calculating its size.
When you change the style of the children of the grid to display:none, or to turn them into abspos, or to use grid-row or grid-column to explicitly place them into implicit tracks, you can affect the number of tracks implicit tracks, and if they have a non-zero fixed min track sizing function, this in turn affects the size of the grid even if you ignore them when sizing the tracks. But since the goal of size containment is that whatever happens inside the element has no effect on the size of the element, this cannot be allowed. |
Well, a box either intrinsically sized, or has a definite size from the style properties, or stretch fit into a definite available size. There are no other cases, hence the part I removed is unnecessary and just adds confusion. Obviously, when the size is definite then whether or not it should be consider to have no contents when calculating that size is irrelevant. So the only case that remains is intrinsic sizing. Anyway, I believe we agree on the behavior, just not which wording to best describe it.
OK, so you're advocating for option C (#4931 (comment)) then, if I understand you correctly? |
The CSS Working Group just discussed The full IRC log of that discussion<myles> Topic: Clarify that contain:size affects track sizing<Rossen_> github: https://github.com//issues/4931 <myles> florian: mats palmgren and I were having a long discussion about what the spec currently means. We are coming down to agreeing what's desired, but not what the actual words in the spec say. contain:size says that when you try to figure out the size of an element or its intrinsic size, you treat it as if it has no descendents, then you do layout. He was wondering does this mean you do track sizing of grid with our without descendents? <myles> florian: AFAIAC, Track sizing for layout, it's not intrinsic sizing. If you have no children, then you have no implicit tracks, then you look at explicit tracks, then you know the grid, and you lay out. <iank_> q+ <myles> florian: But if there is intrinsic sizing of the tracks, should this be canceled out? <Rossen_> q? <myles> florian: Earlier, number of tracks is not described as being sizing <myles> florian: The conclusion is that no, you don't create implicit tracks for the grid, because that would change the size of the grid. But when you do a layout, you calculate the track size property. We are now agreeing now. But we are disagreeing on whether the words in the spec say that <myles> florian: If your track sizes have a fixed min number of pixels, then you incorporate it, and do a full layout. <myles> oriol: Currently in chromium, the contents are taken into account. They are placed in the grid and they can create implicit tracks. <myles> oriol: This defeats the point of having size containment, since now the size of teh grid container can depend on contents. But the dependency is not on the size of hte contents, but instead their computed style <myles> oriol: But instead this would be style containment... but I'm fine with what florian is proposing. <myles> florian: Size-containment means your own size is unaffected by your children. Not that your children's sizes are contained. <AmeliaBR> Size containment is supposed to prevent intrinsic sizing from affecting parent/siblings. So shouldn't affect internal grid layout beyond the size of the box. <myles> florian: To achieve that, we need children not to create implicit trakcs <Rossen_> ack iank_ <fantasai> +1 to AmeliaBR's description <myles> iank_: I agree with that model. However, we may want to consider changing what size containment means, given container queries we just discussed. Currently, your grid template columns will affect the inline size of your element. In david's proposal, if you have a container query and it can affect some subset of properties, grid template columns can't do that. <myles> iank_: There are only 2 layout modes that are special here: grid and multicol. <AmeliaBR> q? <myles> iank_: So we could change size containment to act more like block and flexbox, and ignore grid template columns. This means that containment queries, if you can style a certain amount of properties, grid template can be one of these properties <myles> dbaron: I think we're a few steps away from determining whether this is a possibility at all. But it sounds reasonable <myles> iank_: I worry if we don't consider this soon, we'll start closing off opportunities. <myles> iank_: This might be a better way to write the spec and avoid this whole problem. <dbaron> s/reasonable/reasonable. Not sure we're ready to make decisions based on it, but also not sure we want to foreclose it./ <AmeliaBR> q+ <myles> florian: I think this is compatible with the goals. If we do get the ability to do container queries, that could make this restriction worth it. Later, we might also want a stricter kind of containment, if that's valuable <myles> iank_: I would push back against that. Having one grid+multicol ... people understand what size containment does. It matches that mental model. I don't think we should add unnecessary complexity there. <myles> florian: Thinking through this, if you have a grid that is a block-level child of whatever's around it, it will be sized with width, and everything isfine. But if its intrinsic size ... [missed] <Rossen_> ack AmeliaBR <myles> AmeliaBR: There seems to be a bit of confusion of whether the issue is about which properties affect the calculated size that you're containing to, vs once you've contained that size which features are you restricting. Do these two necessarily have to be the same? Are we allowed to look at the column properties and figure out they determine a minimum size, and say "okay that's the size we're containing to we can figure out just by looking properties on this <myles> element, no need to look at children" <Rossen_> q? <myles> AmeliaBR: But then in another case, the column properties might be auto, or otherwise based on intrinsic size of the child contents, and so in that case the size that would be contained would be dependent on other properties on the element we're containing. When we go to lay out the grid inside that element, can we still lay out that grid based on the children and if the results from laying out the grid is larger than the container size, then we get scrollbars <myles> florian: The spec say you have to do that. That's what i was trying to say when I wrote it. Mats disagrees that's what it says. Perhaps either TabAtkins or I should rewrite it to make sure it says that. But maybe if container queries happen, this will need updating <myles> florian: Notice that this is further along on the req track than grid is, so maybe this text should be done in grid instead. <Rossen_> ack fantasai <myles> fantasai: I agree with florian. This is the most straightforward way to define it. <myles> fantasai: Even if we weren't tracking these specs process-wise. It could be called out in contain <myles> florian: There's a note already. <myles> fantasai: yes. iank_'s point about wanting grid-template-columns to be changeable is a good one, but if we're not doing that, then if the idea that it doens't create intrinisic tracks is unworkable, we have to put them in tracks somehow, we can't put them all on top of each other <myles> florian: There are two phases. 1. size 2. lay out. For the first phase, pretend it has no children, don't consider implicit tracks but do consider explicit ones. 2nd phase: Of course we consider implicit tracks. <fremy> (+1 to proposal) <myles> fantasai: Proposal: Clarify the contain spec about ignoring children when doing intrinsic sizing, but don't ignore for layout <myles> fantasai: And open a second issue about whether grid should have g-t-c be ignored for intrinsic sizing, and put it in the grid spec <myles> iank_: It should go in the containment spec. The min and max content size is affected. <myles> florian: for multicol as well? <myles> iank_: Potentially. columns won't affect intrinsic size of multicol. <myles> florian: What if you say columns: 3 300 column-gap: 300, what's teh benefit of [missed] <myles> iank_: Inside the container query, you can change the size of the contents, but you can't change the number of children <myles> iank_: This is a strictly better if we get container queries. Now is the right time to do it. <myles> Rossen_: I see support in IRC by fremy <fantasai> s/min and max content/min- and max-content/ <myles> florian: This will also be a change in form controls, which are weird and not completely replaced elements, and are not 0 when they are empty <myles> florian: I ran into a bug about this. Dropdowns with no children are big enough to not only have the arrow but also have some space where its contents would be <myles> Rossen_: What is the summary? <myles> florian: Proposal: Replace what we have in .1 of size containment, where it says [reads] <fantasai> Kinda discussing 'contain: size' vs 'contain: children' seems like... <myles> florian: And to say that all elements are .... no. we don't want 0. we still want to fill available width. <myles> florian: If you're a block and you're size contained, you're supposed to fill your container <myles> iank_: I agree it should be potentially an exception for replaced elements and non-replaced elements <myles> Rossen_: Let's take these one by one <myles> Rossen_: For the contain spec, we are going to add a clarification of ignoring children for intrinsic sizing purposes and not layout <fantasai> ... were 'contain: size' treats min-content and max-content sizes as `contain-intrinsic-size`, and 'contain: children' pretends there's no children for purpose of intrinsic sizes... <myles> florian: We're either going to tweak the wording editorially, or we're changing that min-content and max-content width and height are 0 <myles> dbaron: I'm nervous about addressing min content and max content only without also saying what the effects on layout are. Size containment affects both of them. <myles> florian: There is no effect on layout. <myles> dbaron: I think there is from one layout model to another. That's correct for grid, but I don't think every layout model lays out that way. For example, block does in one dimension but not the other <myles> AmeliaBR: How about "for the purposes of determining size, min-content and max-content are 0, but they go back to normal when laying out children?" <myles> dbaron: I'm trying to think through it again. <myles> dbaron: don't wait on me. <myles> Rossen_: It's valid to not resolve on this if we're not ... <myles> florian: We've uncovered something new and significant. There is a benefit to simplify the definition for the purpose of container queries, then we can go back to github to see what it would be. <myles> Rossen_: It would be great to consider more than grid in here. Would this ever be possible in tables? <myles> florian: Size containment does not apply to various table parts <myles> iank_: Table size containment is broken in many browsers <myles> Rossen_: let's end here. <myles> Rossen_: florian, you have lots of feedback here to put into the issue. Let's continue making forward progress there. Feel free to open the grid-related issue if we need to go that way. <myles> Rossen_: That's everything for this one. Thank you! |
Hmm. I accidentally let this sleep for a little too long. In summary, at this point, I think we have narrowed it down to two possible approaches: α) Clarification of the current spec, to stay true to its initial intent, which would have you size the element as if it was empty, including explicit grid tracks sized as if they had no element placed in them, and not including any implicit track since they wouldn't be created in the absence of content; then in a second phase, perform layout of the content within the now fixed-size box normally. Specific wording to be tweaked, but it's in the spirit of "solution C". β) Make contain:size more aggressive, and actually suppress explicit grid tracks as well during the sizing step (but still lay everything normally in phase 2). This isn't really necessary for the purposes of contain:size itself, but if we want to use it as a building block for some kind of container queries thing, that could be useful. Exactly how container queries is going to work (if it ever does) is unclear, but logically, in order to avoid circular definitions, you would not be able to set conditionally by query any properties that can affect the size of the object you're querying. Which means that grid-template can't be something you could change in response to a query about the size of the grid container, unless we made sure that contain:size suppresses its effect on the container’s size. If we apply the same principles to multicol:
Typically, size containment isn't used without manually providing a size: For out-of-flow elements, size containment isn't useful, and for in-flow elements, size containment without providing a size results in jumbled / overlapping layouts. So for most uses, the difference doesn't actually matter. The one case where it would matter is 1D size containment. Having the inline dimension of a block level element be size-contained, without specifying a size manually, would be useful, and could very well serve as a basis for container queries. This is discussed in #1031 That said, as discussed in that issue, it's not clear yet whether whether 1D size-containment + container queries is going to be possible at all. Unless I am missing something about the usefulness of β with 2D size-containment, I think this leaves us with a few paths forward:
|
This is an editorial adjustment, drawing from the non controversial parts of #4931. This does not on its own resolve that issue.
I've made an exploratory pull request in #5643 (attempts to) implement option α, and can be turned into β with the addition of a single sentence. |
This was resolved by merging #5643. The change is applied directly in level 2, and the corresponding change is marked up as a candidate correction in level 1 (to be published soon). Closing. |
Consider the following case:
My understanding of the CSS Containment spec is that the intent of
contain:size
is that all size calculations should be done as if the element has no children:https://drafts.csswg.org/css-contain/#containment-size
Chromium and Gecko agrees that the content-box size in the above case is 0x0, which is correct. I tend to think that the track sizes also should be zero and thus that it should render the same as:
Neither Chromium nor Gecko does that currently, but I intend to fix this in Gecko (bug 1488878).
I can't find any spec text dealing with this case explicitly though, so I would like CSS Grid to clarify that when the Grid container has
contain:size
the Track Sizing Algorithm should be run as if the container has no items. This will have the effect that any intrinsic track sizes will be zero.The text was updated successfully, but these errors were encountered: