w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.36k stars 641 forks source link

[css-sizing][css-grid][css-flexbox] Intrinsic Sizes, Scroll Containers, and Grid/Flex Sizing #1865

Open fantasai opened 6 years ago

fantasai commented 6 years ago

Grid Layout and Flex Layout use automatic minimum sizes (min-content, by default, but depending on the specified min-width/min-height) to prevent grid items and flex items from shrinking too small to be usable. There's an exception to the use of min-content for grid/flex items which have overflow set on them, since authors expect those to shrink below their min-content size. But this exception doesn't follow through to descendants of the grid/flex item, resulting in confusion and frustration for authors. Issue #1777 was filed as a result of such confusion, and Dave Rupert posted http://daverupert.com/2017/09/breaking-the-grid/ discussing the problem.

This issue is filed to look into ways to ameliorate the problem: if we can make things Just Work as authors expect, that would be better! Of course Flex and Grid should be affected analogously, thus tagging them both in.

fantasai commented 6 years ago

Fwiw, https://github.com/w3c/csswg-drafts/issues/765 will likely solve the problems with replaced elements in Dave Rupert's post. (Authors will need to use max-width: 100% to get the right behavior, but this doesn't seem unreasonable.)

Solving scrollable <pre>/<table>/whatever inside the grid item is harder, it would require redefining the min-content size of such items; and afaict that would only help in the inline axis.

fantasai commented 6 years ago

Discussed this with biesi on Saturday... current idea is to solve this in the inline axis for blocks and in both axes for flex and grid items by assuming a min-content size of zero for overflow != visible.

css-meeting-bot commented 6 years ago

The Working Group just discussed intrinsic size of 'overflow: auto/scroll' and its impact on auto-sized grid/flex item ancestors.

The full IRC log of that discussion <gregwhitworth> Topic: intrinsic size of 'overflow: auto/scroll' and its impact on auto-sized grid/flex item ancestors
<astearns> github: https://github.com/w3c/csswg-drafts/issues/1865
<gregwhitworth> fantasai: grid and flexbox show this issue, where people have an element with a scrollbar and they put it among a whole bunch of other content
<gregwhitworth> fantasai: it forces that has a min-content size which defeats the purpose of the scrolling the author defined
<gregwhitworth> fantasai: this leads to a lot of confusion for authors
<gregwhitworth> fantasai: they're already handling their overflow and it would be nice if they just worked
<gregwhitworth> fantasai: this was filed that would allow us to come up with a way for this to work
<dbaron> q+
<gregwhitworth> fantasai: I was talking with cbiesinger on Saturday to try and have the min-content zero'd out
<gregwhitworth> fantasai: the min-content contribution which has overflow be 0, but not the logical height depending on its overflow. If you did this you'd have to relayout in flow content to determine it's min and max
<fremy> q+
<gregwhitworth> fantasai: it's an idea, we're looking for other ideas
<dbaron> q-
<gregwhitworth> dbaron: The thing with overflow that is not visible the size is the content within it, it has to propagate through it if it's the only thing
<gregwhitworth> dbaron: I tend to think, that there is not going to be a thing that we can do to solve this with a property that allows them to choose the thing that they want
<gregwhitworth> dbaron: I think there are two different scopes
<cbiesinger> q+
<Rossen> q?
<gregwhitworth> 1. intrinsic control intrinsic width that has overflow
<gregwhitworth> 2. properties that allow assignment to the intrinsic widths
<gregwhitworth> dbaron: the advantage of the first one is it gives more room for auto behaviors that do the right thing
<gregwhitworth> dbaron: the advantage of the second is it is strictly more powerful
<fantasai> q+
<Rossen> q?
<Rossen> ack fremy
<gregwhitworth> fremy: I wanted to note that we had a similar issue in the table spec
<gregwhitworth> fremy: if you have a % height and you're overflowing in a non visible way we should resolve to 0
<gregwhitworth> fremy: the author intent is pretty clear here
<gregwhitworth> fremy: to me this makes sense and is generalized
<Rossen> q?
<gregwhitworth> fantasai: for grid and flex items specifically the automatic minimum size is not triggered on items that are not with overflow that is not visible but it does impact content contribution
<gregwhitworth> cbiesinger: you said that the single items need the content contribution to propagate through
<gregwhitworth> dbaron: because people will use it to hide things rather than scroll it
<gregwhitworth> fantasai: that's a good point
<fantasai> s/use it/use 'overflow: hidden'/
<gregwhitworth> dbaron: you're talking about zering out the min-content sizes
<gregwhitworth> fantasai: yeah, just the min-content size
<smfr> s/zering/zeroing/
<Rossen> q?
<Rossen> ack cbiesinger
<gregwhitworth> dbaron: presumably the min-content sizes don't matter
<gregwhitworth> cbiesinger: for the min size of flex and grid would make it zero in this cases
<gregwhitworth> dbaron: in many cases you want them to get smaller but not to 0
<gregwhitworth> fantasai: a lot of the cases that are here the minimum would be controlled by other content that happens to be there
<gregwhitworth> fantasai: if they don't want it to get to 0 they can set a min size on the flex or grid item
<fantasai> or on the scroller itself
<gregwhitworth> dbaron: the other thing I worry about here is compat
<gregwhitworth> cbiesinger: that is concerning
<gregwhitworth> dholbert: Chrome already does this correct?
<fantasai> This is more understandable than having a scrollable descendant of a grid or flex item several layers deep in a subsection of a subsection cause the flex/grid item's width to explode out
<gregwhitworth> cbiesinger: I don't think we do that, but we do is for column flex we don't give it a min-height
<gregwhitworth> dholbert: I thought there was something there for overflow: scroll
<gregwhitworth> cbiesinger: I'd need to look at it
<cbiesinger> s/column flex/nested column flexboxes/
<fantasai> Proposal in two parts:
<fantasai> 1 flex/grid items with overflow != visible | hidden have min-content contribution of zero
<gregwhitworth> Rossen: I read through the post about this issue, but I'd want more use cases for this. I am not going to object, but there will be compat issues for this
<gregwhitworth> Rossen: dbaron any objections?
<jensimmons> Rossen: can you speak up? You are very quiet. Or move a mike closer to you.
<fantasai> 2 inline dimension of block with ovefow != visible | hidden has mincontent contribution of zero
<gregwhitworth> dbaron: I wouldn't object, but I'd like to discuss the compat implications
<gregwhitworth> Rossen: we can discuss this on the side - let's not rush the resolution
<gregwhitworth> dbaron: I would be hesitant to come up with something too magical
<gregwhitworth> Rossen: unless there is something else to be discussed
fantasai commented 6 years ago

To write out the proposal in more detail:

This should address most of the cases where people are confused by the current behavior. Authors who want such box’s min-content size taken into account can use min-width: min-content which is a relatively straightforward fix for that issue -- the current behavior has effects that cross through descendants which is what's particularly surprising and problematic about it.

css-meeting-bot commented 6 years ago

The Working Group just discussed Intrinsic sizing and containers for grid/flex sizing.

The full IRC log of that discussion <Rossen> Topic: Intrinsic sizing and containers for grid/flex sizing
<Rossen> github: https://github.com/w3c/csswg-drafts/issues/1865
<TabAtkins> fantasai: We discussed yesteray this problem of, in flex and grid we have implied minimum size, and people put stuff in there with scrollbars, expecting that to handle overflow, but because we'r elooking for min-content size *including* overflow, stuff gets too big and it's awkward
<TabAtkins> fantasai: Don't know how to fix it, because it's a deep descendant
<TabAtkins> fantasai: We opened an issue to find better ways here
<TabAtkins> fantasai: Proposal is that grid/flex items that have non-visible overflow ignore their content for the purpose of calculating min-content contribution
<TabAtkins> fantasai: In both axises
<TabAtkins> fantasai: And block boxes do the same thing in the inline axis
<TabAtkins> fantasai: Excluding the block axis because it's awkward and idfficult to compute
<TabAtkins> fantasai: dbaron brought up the point that you might want to consider overflow:hidden different from scroll, because it's sometimes used just for bfc, nothing to do with clipping. That's probably only relevant for blocks.
<TabAtkins> fantasai: For authors that want the min-content size to handle the sizing, they can explicitly use "min-height: min-content"
<TabAtkins> fantasai: I think this will give more intuitive behavior; people wont' be as confused when their items get much wider than expected
<TabAtkins> fantasai: And for hte people who do need to have this old behavior, they can just use min-content keyword
<TabAtkins> TabAtkins: I'm confused - I thought this was about *descendants* of flex/grid items
<TabAtkins> fantasai: Right, but those descendants might be flex/grids again
<TabAtkins> fantasai: So a block with auto-size in the inline axis, and the flexbox container says "how much space does my content want?" and the block says "THIIIIIIIIIIIS wide" and the flexbox gets huge
<TabAtkins> fantasai: So if the block reports that it's 2ems wide (just padding), the flex container can say "2ems here for this scroll container, 3ems for that word", and then becomes 3ems wide, and the extra stuff will scroll as intended.
<fantasai> s/auto-size/auto-size and scroller/
<TabAtkins> fantasai: So the intrinsic size of a scroll container is dictated by its contents. The fact that it has a scrollbar is irrelevant to its contribution; but in practice, you put a scrollbar on it, you're *okay with* it shrinking, so it should be able to shrink below the min-content size.
<fantasai> (and if you don't want to, you can set min-width: min-content)
<TabAtkins> dbaron: Trying to see how specific it is to grid/flex
<TabAtkins> fantasai: Currently not specific. it would effect a float or table-cell that contains an element with overflow:scroll, *if* that float's size is dictated by the size of the overflow element
<TabAtkins> dbaron: I suspect we can't change the float/table behavior, we're probably stuck with this.
<TabAtkins> TabAtkins: So just min-width/height:auto, then
<TabAtkins> gregwhitworth: We resolved about something similar on tables yesterday
<TabAtkins> fantasai: The cases effected by this proposal would be where author sets overflow:auto/scroll, but nothing ever scrolls because the box is always big enough to fit its contents. This seems weird.
<TabAtkins> fantasai: Where the overflow-controlled box is the one dictating the size of the container, such that it never ends up needing to overflow. Seems kinda odd.
<TabAtkins> fantasai: Usually when you ask for overflow, your size is dictated by something else, such that you might have overflow.
<TabAtkins> TabAtkins: I think this needs more thought and compat analysis before I"m comfortable with this.
<TabAtkins> fantasai: Should be able to do it for flexbox and grid, at least, which would solve a lot.
<TabAtkins> fantasai: Currently we say if you have overflow:non-visible your automatic min-size is zero, but your min-content contribution is not zero.
<TabAtkins> fantasai: So I think it's safe to say your min-content contribution is also 0.
<TabAtkins> TabAtkins: I'd still want some thinking time about this, even for the limited case.
fantasai commented 6 years ago

Proposal in two parts:

  1. Grid items and Flex items with oveflow != visible ignore their content when calculating their min-content contribution (unless opted into that behavior explicitly by setting their width or min-width--a specified width (such as width:100px or width:min-content) always takes precedence over one implied by the content when calculating the min-content contribution).
    • Currently we have a rule that zeroes out the value of min-width/min-height on such boxes, but the min size is just a floor on the min-content size: e.g. if a block has a min-width of zero (the default) its min-content size is still based on the content. This proposal address the min-content contribution.
  2. Block boxes with overflow-inline != visible and overflow-inline != hidden ignore their content when calculating their min-content contribution (〃).
    • Block boxes don't have special behavior for overflow: hidden because that is frequently used to mean display: flow-root. (Flex and Grid items don't need this exception because they're flow-roots by default.)
    • Block boxes don't have special behavior for the block axis because a) it requires multiple layout passes through the BFC in which the block participates if we need to propagate this up, due to floats and margin collapsing and other fun b) it's not required by the use case for addressing this issue on blocks, which are only about their inline min-content contributions.

The proposal directly address the expectation that authors have that an element with scrollbars is “squishy” because its overflow is already being handled by the choice to scroll. It solves the problem of arbitrary descendants of a grid or flex item unexpectedly expanding its minimum size: this action-at-a-distance is the source of all the confusion and frustration around this issue. (For example, an overflow:visible flex item, which resolves the default min-width:auto to its min-content width, can accidentally get super-wide because of a scrollable pre nested somewhere deep in its descendants, and there's no obvious way to track down that the pre is the element causing the problem.) In cases where the scrollable box is squished too far, the solution is to add an explicit min-width or min-height at the point where there's a problem, which is an understandable and intuitive fix.

Downsides: Potential web-compat where an author set overflow to a scrollable value expecting that the box would set the size of its container such that this scrollable box has no overflow and doesn't scroll. (Why are you doing this.) Scrollable flex/grid items may shrink down to zero, which isn't very usable, if the author didn't think about handling narrow screens. (E.g. grid-template-columns: auto 1fr with scrollable grid items; or equivalent layout in Flex.)

css-meeting-bot commented 6 years ago

The Working Group just discussed [css-sizing][css-grid][css-flexbox] Intrinsic Sizes, Scroll Containers, and Grid/Flex Sizing.

The full IRC log of that discussion <dael> Topic: [css-sizing][css-grid][css-flexbox] Intrinsic Sizes, Scroll Containers, and Grid/Flex Sizing
<dael> github: https://github.com/w3c/csswg-drafts/issues/1865
<dael> Rossen_: fantasai can you take this?
<dael> [silence]
<dael> fantasai: This was the issue about when you have a flex or grid item andinside it there's really wide content that has scrollbars.
<dael> fantasai: When you put this inside a flex item it triggers the impl min siz which looks at min-content size. Usually it's on the smaller size, but for something like this it could be really really big. Bigger then you expect, esp if you have scrollbars in there.
<dael> fantasai: But you don't get scrollbars because the ancestor asked for the min size.
<dael> fantasai: This is causing a lot of author confusion because some ancestor is making it blow up. THe work arounds are not super objvious.
<dael> fantasai: Suggestion when there is an overflow scroll the min-content contribution should be 0.
<dael> fantasai: That would prevent this from happening.
<dael> fantasai: There are some compat restrictions. For now proposal is: a) don't do this to a block in the block axis and b) don't do it for blocks that have overflow: hidden b/c that's often used to create a flex-root
<dael> fantasai: If a box has overflow not visible and not hidden and it's a block in the inline axis its min-content contribution assumes 0. If it's a flex or gird item we do that for any value of overflow that's not visible in both axis
<dael> fantasai: We believe this would solve most cases. The fix if it's too small is to apply a min-width which is a fairly understandbale fix.
<dael> Rossen_: Thanks fantasai
<dael> dbaron: This sounds like a substantial change to existing behavior.
<dael> fantasai: Yes.
<dael> fantasai: On flex items and grid items prob won't be too surprising. APplying to blocks...if you aheva s crollable block and you're expecting inline size of that block to control the size of its ancestor by sizing so it won't scroll, then your layout would change
<dael> fantasai: We can split into two parts, do for grid and flex and can we do for block.
<dael> dbaron: If you do it for one but not the other you're changing from one concept of min-content size to 2.
<dael> fantasai: Min-content contribution. We already haves pecial behavior for flex and grid when overflow is visible. This is implying the same thing where we don't consider the content for min-content contribution
<dael> dbaron: Isn't this non-local? It's arbitrarily deep descendents.
<dael> fantasai: No. This is if a paricular element is flex or grid and has overflow not visible we don't look at its content when looking at its own min-content contribution.
<dael> fantasai: WE're assuming 0 for the purpose of calc the min-content contribution of that item and this will fix the ancestor issue.
<dael> dbaron: Only if the descendent is flex or grid.
<dael> fantasai: Yes. That's part 1. Part 2 without would apply to regular block would fix it for block. BUt it's a local problem.
<fantasai> s/problem/effect, to fix the action-at-a-distance problem/
<dael> dbaron: Seems like you're saying the compat thing only solves half the problem. Given how widely flex and grid are used i"m not sure part 1 is even web compat.
<dael> Rossen_: Certainly not for flexbox. I'd be more concerned about that then grid at the moment, but definitely concerned about flexbox.
<dael> dbaron: Any sign that impl are not interop?
<dael> Rossen_: I don't believe so. fantasai ?
<dael> fantasai: I don't believe so either
<dael> fantasai: I think the behavior is more in line with what authors expect. When then set it to be scrollable you don't expect it to force the ancestor to give enough space for you not to scroll. I think this would make flex and grid more intutive to authors.
<dael> dbaron: I don't think we can change without more evidence it's safe.
<dael> fantasai: Fair. I guess we can discuss if we want to change if possible, then we can look and see if it's possible. Not make the change until there's more data.
<dael> dbaron: My gut is it's not safe and therefore not worth exploring. Particularly the half change doesn't seem sensible.
<dael> fantasai: The thing is the only case...for a block element by itself inside a container you can size it with %. For block elements they're i na flow and they'll take their auto size. The effect in that axis...we don't distinguish between max an dmin content in the block ais. If we try and apply to a block in a block axis we have to introduce this concept and then have the min and max calc differently.
<dael> fantasai: The you have a set of blocks and they have a min and a max size and you have to calc layout twice to get the min size.
<dael> dbaron: I'm not worried about block axis part. I don't agree with these concepts existin gin the block axis. It's the not doing it for block that's the half chnge.
<dael> fantasai: Ideally I'd like to do both, yes.
<dbaron> s/for block/for block, just for flex and grid,/
<dael> Rossen_: And the second part is a lot scarier meaning doing both would be a lot harder.
<dael> Rossen_: This is going to sizing right or flex and grid?
<dael> fantasai: sizing
<dael> fantasai: In terms of collecting data, that's a project but I'm willing to try and work on it b/c this issue is causing a lot of problems for authors.
<dael> Rossen_: Can you point to some of the confusion?
<dael> fantasai: There's a bunch of websites trying to explain the fix and the fix isn't obvious.
<dael> fantasai: There's a pre several items deep that's causing this and it's not obvious and it's getting exploded. And the explosion is a min-width so even setting a width it won't flex the way you expect.
<fantasai> s/width/flex-basis/
<dael> Rossen_: Do you want a resolution?
<dael> Rossen_: More support to work on it? Sample interest?
<dael> fantasai: What I've gotten is we want more data on if it's compat. I'd like to know if the web compat comes back as no problem, would people want to make this change? If the answer is no there's no point in getting data.
<dael> Rossen_: As an Edge impl, the impl itself won't be that difficult so if you're probing to see how impl this it, it is fairly doable. But I'm fairly concenred with breakage, I'm sympathetic to dbaron's case.
<dael> fantasai: And th epoint is collect data. But if we get data that says it's okay, would you accept the change? If you still don't like the change we've wasted the time to get data. Is it worth it to collect the data?
<dael> Rossen_: Okay. If anyone wants to push back on any reason other then interop concerns, this is your chance.
<gregwhitworth> https://log.csswg.org/irc.w3.org/css/2017-08-03/#e843776
<dael> gregwhitworth: While people think, I want to loop back and say we solved a similar problem for tables. I'll link to the minutes. We hit a similar problem where we have this very scenario.
<dael> gregwhitworth: I personally feel there is enough there. I'm not sure if it's worht gathering data. We have compat issues with the inverse.
<dael> fantasai: What you're saying is we had an issue with a direct desc of the table which has scroll does not contribute it's min-content. IT was 0.
<dael> gregwhitworth: Yeah, it's floored out. THe layout is done and then Chrome fills out. IN Edge we give it the 100% and then the accept term of service ends up offscreen.
<dael> fantasai: That's an ex of us having to make for compat reasons the fix being proposed. THis proposal is doing that same kind of fix more generally.
<dael> fantasai: Same use cases.
<dael> fantasai: Concern for data wasn't if we needed use cases to see if there's author want, this was to see if we can do it without breaking the web.
<dael> gregwhitworth: To answer the question better, if there's positive use cases showing people wnat this and you bring back data saying it wouldn't be a problem, I would be shocked if people pushed back.
<dael> Rossen_: I also said that impl % resolution for padding was easy for us and it wasn't for others. I'm only speaking for edge.
<dael> fantasai: My understanding is becaue it's a local effect it's just a switch on when computing the min-content not to do some extra work. I don't think it's generally difficult to impl.
<dael> Rossen_: We're pretty much top of hour. For fantasai to proceed we need to hear there are not strong obj. Most people are worried about interop. gregwhitworth pointed out some issues where peole need the opposite for tables which would bring more arguements against making it for blocks.
<dael> fantasai: gregwhitworth 's argument pointed out people are having this behavior for specific tables. It's a point in favor of people expecting the proposed.
<dael> Rossen_: Okay.
<dael> Rossen_: I'm not hearing any objections. fwiw continue with this.
<dael> fantasai: So the conclusion is we expect to accept the proposal if fantasai can get data that's it's webcompat.
<dael> Rossen_: Yes. I think going to the step of data is worthwhile.
<dael> dbaron: I would hesitate to accept the half proposal, though.
<dael> Rossen_: +1 to db
<dael> fantasai: We expect to accep thte full proposal if fantasai can get data it's web compat.
Dan503 commented 6 years ago

I'm glad that this issue is getting traction and I'm pretty happy with the direction that it is going in :)

I don't understand what the ramifications of applying this to block as well are. This seems to be a problem that is specific to flexbox and grid.

If this is applied to block, what effects would that have? Or is that what the point of this gathering data phase is for? To figure that part out?

cbiesinger commented 5 years ago

For proposal 1, this is only for row flexboxes, right? (Reasoning being that the min-width: auto behaviour for overflow: non-visible only applies to row flexboxes too)

fantasai commented 5 years ago

@cbiesinger It should apply to both. Like Grid, Flexbox is symmetric. You won't notice that if your container is block-level, since blocks always lay out at their max-content size (unless they're fixed-height) but if the item’s flex container is itself embedded in a fixed-height flex/grid container, then the distinction between min/max-content starts to matter.

cbiesinger commented 5 years ago

@fantasai but when calculating the inline-axis min-content contribution of an item in a column flexbox, does it make sense to compute the min-content width of the overflow: auto element to zero?

cbiesinger commented 5 years ago

https://crrev.com/c/1377009

cbiesinger commented 3 years ago

https://crrev.com/c/1377009

Just realized I never followed up here; that change was reverted quickly because it broke too much: https://crbug.com/944614 https://crbug.com/941975 https://crbug.com/943496

fantasai commented 3 years ago

Retargetting for css-sizing-4: since it looks like we can't change the past, looking into adding a switch (similar concept to box-sizing, except it's a more confusing concept...); see https://github.com/w3c/csswg-drafts/issues/4585