-
Notifications
You must be signed in to change notification settings - Fork 666
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-3] Ancestor Layout Loops with Single-Axis Containment #6426
Comments
I don't understand how the cross-axis overflow case is any different for single-axis containment and container queries than what is currently the issue with overflow:auto and contain:size. Regarding maintaining the same inline-size, we cannot do that even for contain:size, I think. In this case, the inline size of the #contain element depends on its #spanner content via the scrollbar it triggers: <!doctype html>
<style>
#scroller { width: 400px; height: 400px; overflow: auto; }
#contain { contain: size; border: 2px solid green; }
#spanner { height: 2000px; border: 2px solid red; }
</style>
<div id="scroller">
<div id="contain">
<div id="spanner">Spanner</div>
</div>
</div> |
@lilles That's because EDIT: I'm wrong, and Rune is right. |
So for all(?) of these cases roughly fall into this pattern:
For this case the parent layout algorithms always walk forward. They don't go backwards. The easiest to look at here is the float case: https://codepen.io/miriamsuzanne/pen/mdmJRxW E.g. if we see that a fragment has a smaller block-size in area 2 we don't suddenly go backwards to try and get it to fit in area 1. This is somewhat implied by a lot of algorithms, for the float case we discussed it previously here: |
@dholbert is a bit more familiar with containment and can probably page this stuff in faster, but happy to take a look if he can't :) |
It sounds bit like there simply isn't such a thing as single-axis containment in CSS. Having a confusing and arbitrary seeming set of rules affect layout of the entire parent chain seems like opposite of "containment". It is not obvious to me that that it is a requirement for a useful container query feature though. Maybe the focus should be in ensuring the algorithm makes forward progress and arrives in stable (though not necessarily entirely self-consistent) end state? |
So if I'm understand correctly, the proposed solution is just to let the following behavior sort of naturally fall out (with no explicit fixup/band-aids needed): I think this seems ~fine, though I suspect we may have to go through this same dance on every incremental layout for any change that dirties any nearby boxes. |
The CSS Working Group just discussed
The full IRC log of that discussion<dael_> Topic: [css-contain-3] Ancestor Layout Loops with Single-Axis Containment<dael_> github: https://github.com//issues/6426 <dael_> miriam: It turns out this is hard. We knew that <dael_> miriam: I tried to document 4 known instances where content changing size on 1 axis, generally block, has impact on available size for inline. So if we try and contain inline only get a loop <dael_> miriam: Generally have a pattern where outer ancestor, element contained on inline axis, inside of that contents responding to container query <dael_> miriam: With those three nested bits, a few of the issues are orthogonal writing modes. 2 other cases that are common. Ancestor is overflow scroll ad the contents can trigger scrollbar on ancestor which changes inline space available <dael_> miriam: Another is floats as they get taller or shorter how they stack might change <dael_> miriam: In my first document I wrote out the brute force solutions. They're not ideal for users. iank_'s idea is better <dael_> iank_: I need to study one of these a bit more but they all fall into effectively we layout a child once with given space, read child height, and based on that give it a new available space. <iank_> https://www.software.hixie.ch/utilities/js/live-dom-viewer/?saved=9775 <dael_> iank_: Fundamentally need to make sure we never walk backwards. This is true today <dael_> iank_: I pasted in irc an example ^ <dael_> iank_: Orange box and inside it has a child with an a-r. Conisder width first, get height where we can't fix. Then consider second of 50px. All engines walk forwards like that. <dael_> iank_: We don't try and say now that I'm this height maybe i could fit back here after all <dael_> florian: Do you mean this is hte end of hte line principle we don't need the pieces miriam highlighted or that it solves them all? <Rossen_> q? <florian> q+ <fantasai> me q- <dael_> iank_: I think we state it and it solves them all. Orthogonal. We layout with one set of contstraints, layout, adjust. We move forward. <fantasai> s/me q-// <Rossen_> ack florian <dael_> florian: I'm a bit concerned this is different than float. We should avoid making css accidently stateful <dael_> florian: Float, ancestors are not effected by float in the same way <dael_> florian: Roughly I feel the way miriam proposed is annoyingly specific but need to do it to avoid vague or stateful <dael_> iank_: I don't think it's stateful. We have a bug on orthogonal, but with that case to compute intrinsic size for the orthogonal child we need to lay it out with some available size. <dael_> iank_: We layout with that size. may effect size of the parent. Now when we do layout pass we give orthogonal child different constraints and it lays out differently <dael_> florian: That sounds true <dael_> iank_: If you can come up with a case you think is stateful happy to access <dael_> iank_: Orthogonal is hard b/c engines have a lot of bugs. miriam example shows a bug <dael_> florian: For scrollbar and padding do you think we can get away without hatchet miriam proposed? <dael_> iank_: I think so. A-r is fine, floats is fine, I think classic scrollbars is fine as long as you add them in a particular way. We'll slowly add scrollbars to get to a state. I think it should be okay <dael_> florian: I thought if you didn't have miriam approach you would get a different result if you start on a 800 px window different result then if you start bigger and sthrink <dael_> iank_: No, shouldn't be an issue. That's a browser issue and should be fixed. <dael_> iank_: If there is an ambig set of steps where we need more specific order we should do that <dael_> iank_: When forming a new context in relation to floats we had a specific order on how people should walk through. Pretty much everything else falls into that <dael_> florian: If we go that way we can have a spec that's less magic but we need to be very precise so it's stable and interop <dael_> iank_: yes <dael_> florian: Can someone implementing list the steps? Undefined would be bad <dael_> iank_: Depends what you mean by define <dael_> iank_: We don't have a spec for block layout but we have resolved how floats behave. <dael_> iank_: I can describe how this works for orthogonal children, I think that's well defined <dael_> florian: My ask would be for the 4 cases miriam highlighted which I think are specific enough, could you either point to the spec language that make them non-problematic or propose sufficient spec text? <dael_> iank_: I can work with miriam on that <dael_> Rossen_: Sounds like we're forming consensus around going forward with reasoning captured in the issue by iank_. Additional exercise to figure out where changes have to land <dael_> Rossen_: Anything else to add here? I see people on this issue chimed in <dael_> florian: Great if we can go there. The things proposed are cludges we thought unavoidable. If they're avoidable, great <dael_> Rossen_: In terms of solution anything else to add here? <dael_> dholbert: I think your example with a-r is a good case for something that behaves like this without needing container queries. Good extension of that <dael_> iank_: I think I can create examples as well with time <dael_> Rossen_: We call them test cases; please add them :) <dael_> Rossen_: Let's resolve on path forward. And it'll be iank_ for you to figure out wehre edits should go <dael_> Rossen_: Prop: Accept iank_'s proposal to guarantee full layout algorithm is always forward moving <dael_> florian: Sort of important to get to this in a timely manner. This discussion has been going on for years in GH. If there is a solution, great, but I'm worried we will force other browsers to reverse engineer crhome or do something else if we don't write it <dael_> chrishtr: resolution to go with iank_ proposal? <dael_> iank_: write it down at least for the examples. Part of the problem is large parts of some algos are undefined. Can spac how things should walk forward <dael_> chrishtr: So parts of algo that intersect need to be written <dael_> iank_: Part of issue is float not well defined. List of side effects. most recent for float layout is in a GH issue but not in spec. Pointing to the various places we've resolved <dael_> iank_: For intrinsic size we have it written <dael_> florian: I don't think iank_ proposal is not self contained enough. It's an approach we need to look into more details. <dael_> Rossen_: yes. We don't have specificals <dael_> florian: We agree to try and solve that way. And we go that way and we come back to resolve on details <dael_> Rossen_: Have proposed path forward. Don't have details about specifics, but approach makes sense. You've made your point and people agree. <dael_> fantasai: We had previously declined to publish fpwd because of this issue. If we get to a point we're okay with the issue we should publish fpwd <dael_> previous proposal: Accept iank_'s proposal to guarantee full layout algorithm is always forward moving <dael_> Rossen_: That's the proposed resolution. Obj? <dael_> RESOLVED: Accept iank_'s proposal to guarantee full layout algorithm is always forward moving |
That's unfortunate-but-ok as long as it's somewhat rare. The opposite (i.e. having overflowing content but no room to put the scrollbar) would likely not. |
There is now a draft commit; however there is one more commit coming that moves the part about avoiding infinite cycles to a non-normative note. Based on some offline discussions with several people, I think the TL;DR summary of what it's trying to say is: Ideally, point (a) would be proved by algorithmic analysis, but unfortunately there is no algorithmic spec for block layout, floats etc; just a set of described "effects" of the layouts. I think it's too much to ask to require going through a very long and difficult task of writing it all out as an algorithm and proving that it halts and has a certain runtime performance. Instead, we should make our best effort to find and resolve problems we find, and guide our work with plenty of tests and implementation experience. Detailed version of my reasoning:
(*) Examples: If you graph it in 2D with inline size in the X axis and block size in the Y, the relationship for an |
8574e93 Mostly looks good to me; I left a few comments on the commit about the examples. |
OK, @tabatkins and I made some revisions to this section to a) simplify the note and b) improve the example. I also ported in the size containment exceptions from css-contain-2 and tightened up some of the normative wording. The resulting text can be viewed at https://drafts.csswg.org/css-contain-3/#containment-inline-size |
New text LGTM. |
I think the spec changes above should address both this issue and #1031, pending a resolution to approve this approach. |
@mirisuzanne when you said "should address", you meant it in the "did address" sense, right? Meaning you think the spec text as curently written is enough to resolve #1031 and #6426? |
@chrishtr yes |
Yup seems good. |
The CSS Working Group just discussed
The full IRC log of that discussion<fantasai> Topic: Ancestor Layout Loops<drott> thanks for taking that issue before the hour <fantasai> github: https://github.com//issues/6426 <fantasai> miriam: This has been the main blocking issue for Container Queries <fantasai> miriam: defining exactly how single-axis containment should work <fantasai> miriam: I think at this point narrowing that down to the [audio cut] <fantasai> miriam: inline axis <fantasai> miriam: potential worried about changes to block size impacting available inline size, creating a loop <fantasai> miriam: iank proposed that these are not new issues, and we have existing solutions in CSS, and showed that some of these problems already exist <fantasai> miriam: we wrote a draft spec <fantasai> fantasai: Importantly, both IanK and dbaron signed off on the spec, so from my perspective it must be good enough for FPWD <fantasai> florian: dbaron reviewed earlier version, did he re-review the updated version? <fantasai> dbaron: Don't hold up on me <fantasai> dbaron: I'll get to it <chrishtr> (the updated version is basically the same as the previous version) <drott> (I am out for the next half hour, possibly slightly longer) <fantasai> florian: As far as I'm concerned, if dbaron's OK with it OK with me <fantasai> astearns: So are we proposing to resolve on the draft text? <fantasai> miriam: yes <fantasai> fantasai: And also to publish FPWD <fantasai> astearns: Anyone with concerns about resolving to accept the draft text? <fantasai> astearns: anyone need more time to review? <fantasai> RESOLVED: Accept draft text <fantasai> astearns: since this was the last big issue that we wanted to solve before FPWD, next is proposed FPWD of CSS Contain 3 <fantasai> +! <fantasai> +1 <fantasai> jensimmons: +1 to FPWD, keep seeing situations where not having a WD of this spec is creating problems <chrishtr> +1 <fantasai> astearns: anyone with the opposite view? <fantasai> florian: I was pushing back against this one until this issue was addressed, because unclear if we should publish FPWD without it, but with that cleared I'm good now <fantasai> RESOLVED: FPWD Contain 3 <chrishtr> congratulations everyone, especially miriam! <chrishtr> This is an awesome feature, and a huge milestone for the web. <fantasai> <astearns> +1, very happy to get into FPWD |
In #1031 we identified the need for, and some of the issues with, single-axis containment. Since then Chrome has implemented the basic feature behind a flag – and we've had a chance to explore some of the issues in more depth. We wanted to start a new thread here to provide a collated summary of the issues, and how they relate.
In order for inline-size containment to work, the container has to maintain the same inline-size no matter what happens to the contents inside it – and no matter how much the block-size changes. These are cases where that behavior is difficult to define. We have potential solutions to each individual issue here. But the overarching concern is that all these solutions need to be applied on arbitrary ancestors of the contained element, making their impact expensive for browser engines, and unpredictable for authors.
Hopefully we can attempt some of these solutions in the Chrome prototype, in order to see them in practice.
Cross-axis overflow and classic scrollbars
Demo: https://codepen.io/miriamsuzanne/pen/yLbNgMx (requires classic scrollbars enabled)
If any ancestor has overflow on the container's block axis, then additional block-size of the contents can trigger a scrollbar on the cross-axis. Classic scrollbars for block-scrolling take up space on the inline-axis, leaving less space for the container.
This is likely to a very common scenario, impacting the majority of sites that uses inline-size containment, since the viewport itself uses auto-scrollbars.
This could be resolved by applying
overflow-gutter: stable
to the nearest ancestor withoverflow: auto
on the container's block axis? However,overflow-gutter
is currently limited to a single axis (block-scrolling), and might need to handle inline-scrolling as well, in case the scroller has a writing mode orthogonal to the container.%-Padding percentages in Orthogonal Writing Modes
Demo: https://codepen.io/miriamsuzanne/pen/PomqWVE
When padding is applied to the block axis in percentages, those values resolve against the inline-size of the parent. By restricting single-axis containment to the inline axis, we eliminate the majority of these issues. However, it's still possible to apply orthogonal writing modes to any arbitrary ancestor with block-padding that would respond to the (now cross-axis) block size of the container.
This could be resolved by "zeroing out" any percentage-padding applied to any ancestor on the containers block-axis?
Auto-sized BFCs effected by floats
Demo: https://codepen.io/miriamsuzanne/pen/mdmJRxW
The auto-sized Block Formatting Context (created by
overflow:hidden
) finds space for itself among various floated elements. However, as the contents expand vertically, the BFC has to contend with additional floated elements, and resizes. Note that:This could be resolved by adding
clear: both
to all auto-sized ancestor BFCs?Aspect ratios (and Orthogonal Writing Modes?)
Demo: https://codepen.io/miriamsuzanne/pen/abWOJYJ
Since aspect-ratio implementations are inconsistent, and may have existing recursion issues (see #6419), I'm not confident that I know what issues here are specific to inline containment. Still it seems like something to keep an eye on - especially when orthogonal writing modes come into play.
This could be resolved in by removing the impact of the preferred aspect ratio? Authors who want to maintain a strict aspect ratio can still do that by applying size containment and defining overflow behavior.
The text was updated successfully, but these errors were encountered: