-
Notifications
You must be signed in to change notification settings - Fork 671
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-contain-2] do we need size containment in a single dimension to enable container queries? #1031
Comments
Specifically, what would be needed is 1d |
I think container queries require both size containment and layout containment. |
I agree. What I meant is that you should be able to apply regular layout containment (which we already have) together with 1d size containment (which we don't) to get the effect you described. So authors need both, but the WG only needs to add 1d size containment, since we already have the rest. |
The CSS Working Group just discussed , and agreed to the following resolutions:
The full IRC log of that discussion
|
I would really like this feature to help container query scripts to solve the recursion issue. But is size/layout containment in one dimension even possible? Take, for example, the following structure (assuming that <style>
.wrapper { height: 100px; overflow-y: auto }
.component { contain: size-x }
</style>
<div class="wrapper">
<div class="component">
Content that grows in height via a container query script
when the width gets wider.
</div>
</div> In an edge case this could still lead to an endless loop I think: The width of |
@ausi containment only works on the box that it is applied to; so, in your scenario, you're only containing |
But wouldn’t this re-layout update the width of |
@ausi Yes - but that is how it works today because in scrollbar auto we don't know if we should show one or not, so if you need one we have to do a second pass. Now, based on the containment set you may NOT get to 100px so you won't have that relayout, but again this isn't new. |
The relayout would change the width of As far as I understand it, this means that implementing |
@ausi I mean it's a valid wrinkle, but personally, I think authors would be ok with this type of "two pass" layout as they normally would want the scrollbar to appear, and probably aren't even noticing (in most cases) that two passes are required. As a result, you can still honor the constraint but only once you've answered the question of "does it have scrollbars?" or not. @frivoal @dbaron thoughts? |
I think the “two pass” layout for scrollbars is basically OK for authors. The problem arises if a container query script comes into play. The spec for
The same “no infinite loops” benefit would be required for |
I wonder if this can be solved by making Alternatively, since I believe the problem is exclusively caused by an ancestor having auto scrollbars, maybe that's what we fix: if an overflow:auto element has a descendant with 1d size containment (2d also? not sure), then the scrollbar must be always visible, regardless of whether there is actual overflow or not (with an allowance for overlay scrollbars). |
This would work I think, but it would not be useful for container query scripts anymore.
Unfortunately, I don’t think scrollbars are the only case this could happen. Take for example this code of a <div class="parent">
<div class="inner">
<div class="child"></div>
</div>
</div>
<style>
* { box-sizing: border-box } /*edit: this line was originally omitted, and was added back in later */
.parent {
float: left; /* this makes the width depend on its contents */
height: 100px;
}
.inner {
padding-top: 10%; /* this percentage is relative to the width */
height: 100%;
}
.child {
height: 100%;
contain: size-y; /* would not work in this case */
}
</style>
Two-dimensional |
(edit: this comment was written before `box-sizing: border-box` was added to the example in the previous comment)
Interesting example.
The height of `.inner` depends on the height of the content area of `.parent` , which is fixed at 100px.
So the height of inner is also 100px, regardless of what happens to its padding-top.
The height of `child` is 100% of the content height of `.inner`, so 100px again.
The fact that `padding-top` changes when the non-contained x-axis changes means that the position of `child` will change depending on its width, but it's height will not.
`contain:size-y` means that size changes changes within `.child` that would affect its height don't, so the height of `inner` or up don't change because of that.
So we don't have a loop here: yes, width changes in .child do cause vertical layout changes in ancestors, but those don't affect their content height, and there's no impact on `.child`'s content height…
However, if you add `box-sizing: border-box` on `.inner`, then there is an effect on `.inner`'s content height, and we do have a problem. Damn.
Unlike scrollbars, I don't see any simple way to fix that one.
|
Yeah, I forgot to set the
Neither do I. I would really love this feature, but the more I think of it, the more impossible it seems to me. |
@ausi Thinking again about your example, I think it might not be as much of a problem as I initially though: technically, it's still an issue, but:
So, maybe axis agnostic 1D size containment isn't possible, but maybe 1D *inline-direction size containment is? Well, we still have the problem of scrollbars, but that is a more tractable one. Or are there more situations where this breaks? |
That would be great news.
I don’t know, margin/padding came into my mind when thinking about “what css size in one axis gets influenced by the other axis”. I can’t think of another one just now. |
But with the property Maybe it would be possible to “disable” such features if single-axis containment is used? |
I've been working on this with @andruud, and we have a few ideas for how we might work around the issues. I don't think these two solutions would necessarily be exclusive, but the first certainly feels "simpler" -- and might help us avoid solving the second in more detail. The "pinky promise" (no containment)Our favorite option is to avoid the need for size containment altogether, if we can. What if:
There is some danger that this makes it too easy for authors to stumble into "promise-breaking" behavior, where the container query reports a size significantly different from the final layout dimensions. But the advantages might be enough to offset that concern. It might be worth testing in a prototype. Making 1D containment workIf 1D containment is needed, it looks to me like that would require making some hard decisions about how the cases above fail consistently while maintaining containment. This isn't ideal, but may also be a worthwhile tradeoff for authors. It would take some more discussion, but something like:
|
As for "Making 1D containment work", assuming we've identified all the problematic cases, I think you're thinking along the right lines, and that something like that would solve it. But have we indeed identified all the problematic cases? |
I agree there are likely more 1d containment problem-cases. But I think if we want to go that 1d containment rout -- addressing individual issues as they arise -- we can't be completest about it in the abstract. We'll never know if we have the full list until someone tries building it. |
The CSS Working Group just discussed The full IRC log of that discussion<dael> Topic: [css-contain-1] do we need size containment in a single dimension to enable container queries?<dael> github: https://github.com//issues/1031 <dael> miriam: The context is in thinking about container queries and starting from dbaron initial proposal a few years back <dael> miriam: Easy to imagine how it works with full size containment, but doesn't work for most cases. Works in app-like cases but otherwise falls apart. <dael> miriam: prop is 1d containment so can contain width of element and query against that but allow height to adjust. <dael> miriam: Several cases where height of children changes width of ancestors. Scrollbars and % in padding <dael> miriam: A lot of talk about that making it quite difficult <dael> miriam: anders and I have been pushing on that. <dael> miriam: Going through the ideas backwards b/c 2nd one is thinking through how to address issues as they arrise. If we want 1d can we always trigger scrollbar on ancestors, resolve % to auto <dael> miriam: Not full proposals, but want to push conversation forward <dael> miriam: That's a start on how might address issues as edge cases so 1d containment would work <dael> miriam: anders proposed the pinky-promise approach. Idea here is what if we don't require containment on container queries and we resolve the query as if we have full size containment but allow you to make changes so you get different final size then reported <florian> q+ <dael> miriam: trade offs between but not exclusive of each other. A lot more to resolve on both. Anders isn't here but that's basic context <dael> florian: Author usibility I think pinky-promise works. Cases where children effect cross axis size are rare and easy to avoid. <Rossen_> ack florian <dael> florian: Concerned about implications on impl b/c makes layouts effectively stateful. if doing partial layout you have to do a relayout to figure out size if you hadn't instearted the children you did insert. Order becomes meaningful as well which brings us back to having to do a layout of the anti-page <bkardell_> q+ <dael> florian: Not impossible, but could be expensive. I'm concerned. THe plug the leaks one by one seems more possible. We haven't come up with so many examples. We've so far had 2. Maybe can plus one by one <dael> florian: Seems that by far dominant of 1d is query inline size, not block. The leaks for inline and block are not same. Easier to plug inline leaks. If we jsut worry about those maybe slightly easier problem <dael> bkardell_: In the pinky-promise thing doesn't that wind up negative auto-height? <Rossen_> ack bkardell_ <dael> florian: No, the pinky-promise case you do a container query against width and then you say I won't do anything in layout what would change the width of the parents. As long as you don't have the cases that is does change width of parents everything is fine <dael> miriam: One other complication is inside of floats that shrink wrap, container query would return 0 but layout is quite a bit different <dael> florian: Yeah. But for shrink-wrap this is fundamentally problematic. <miriam> +1 <dael> florian: If there is a use case for that it's a whole different can of worms <dael> Rossen_: We're at time. not sure if we have a resolution we could call. I would urge you to continue discussing on GH <iank_> I'm somewhat not convinced the pinky-promise will yeild the results web-developers expect. <dael> TabAtkins: Not looking for resolution yet, just general information |
This poor wording is my fault. If we need to do another layout pass, which can be the case for e.g. the ancestral scrollbar problem, then the CQ would be evaluated again with the scrollbar effects present. However, if the author then conditionally (based on the scrollbar appearance) restyles things such that a scrollbar would ultimately not be necessary after all, then too bad. You get a useless scrollbar. We're saved by the fact that (in Blink at least) we don't re-layout until we get something stable, we layout at most twice (for the scrollbar case anyway). I don't think it's very practical to maintain an entirely different page-wide reality where some elements are size-contained. I've assumed that we can cheaply and "locally" compute the would-be-contained size for containers whenever they get a new (actual) size. If that's not true, or if we do have "repeat layout until stable" behavior somewhere in a way which can affect the would-be-contained size, then pinky-promise probably doesn't work. |
I believe that's indeed not true, because evaluating them cheaply and locally like that makes layout stateful, which is bad. The current state of the layout should not matter when (re)evaluating the layout. If this is true, when browsers evaluate the layout is an unobservable implementation detail, and they may do it as often or as rarely as they want to, recomputing it for part of the page or for the whole page, and nobody can tell the difference. This is an important quality to maintain, and it rules out the pinky-promise approach (unless we recalculate everything form a clean state every time, but that would be expensive). |
Just thinking out there, maybe we can add inline-size containment by giving the available width rather than the actual width of the container. This has the downside that this might mean we need to redo styling multiple times, if the element needs to be layouted under min/max constraints, but maybe this can be done in one go by computing a few styles options (min-width, parent-size, max-width/unconstrained, ...). This needs some more thought, I just wanted to put this out there, so I remember I had this thouht the next time this is being discussed. |
I just played around with But trying my example from #1031 (comment) results in inconsistent layout jumping between two states. See https://codepen.io/ausi/pen/dyNMYeG @andruud Is it too early to report such bugs on bugs.chromium.org? |
@ausi Yeah, issues like that are expected at this point, but please do report any "interesting" cases you come across nevertheless. 🙂 |
@ausi Thanks for the report. I've reported 1197029. The current code that does an extra pass for auto-scrollbars assumes that scrollbars taking up space is the only way for auto-scrollbars flipping back and forth, but that's no longer the case for container queries, so we need to notify the closest scrollable container that container query evaluations changed during a layout. |
Update: the issue has been fixed in our prototype. |
@bfgeek, @fantasai, and I drafted some initial text for defining inline-size containment in 8577aa2 (and removed block-size single-axis containment entirely). I plan to flesh out the example that's there, and add several more examples demonstrating how inline-size containment behaves in the various 'problem cases' that have been raised. |
Closing. The titular question has been answered, and the spec has been clarified. The resolution wasn't taken in this issue, but the CSSWG did resolve on this topic. |
The definition of container-type:block-size was removed when block-size containment was removed, but the value syntax still had it.
@mirisuzanne Could it be that the changes from 8577aa2 haven't been merged yet? Current ED allows |
@bramus You can still query |
Ah yes, of course 🤦♂️ |
Add support for 'inline-size' and 'block-size' as keywords for the CSS contain property. There is no specification yet, but there are two github issues[1][2]. The syntax implemented here does not allow more than one size containment value per declaration. [1] w3c/csswg-drafts#1031 [2] w3c/csswg-drafts#5796 Bug: 1146092 Change-Id: I79cf3d4cb22e8e2705d5f2f7348f4513e4eac2d7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2653205 Reviewed-by: Morten Stenshorne <[email protected]> Reviewed-by: Anders Hartvoll Ruud <[email protected]> Commit-Queue: Rune Lillesveen <[email protected]> Cr-Commit-Position: refs/heads/master@{#848577} GitOrigin-RevId: 0ecdc725f612e6899bb452b74650101625bb9815
One thing that came up at the extensible Web summit in Boston on Friday was a discussion of container queries.
While I'd previously suggested tying container queries to CSS containment, one thing I realized is that there will be cases where developers want to fix the width from the outside but still allow an auto height, and then do media queries on the container's width.
I haven't thought this through very much, but it seems to me that this may require a concept of layout containment in a single dimension to be exposed from containment.
The text was updated successfully, but these errors were encountered: