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-sizing][css-overflow][css-flexbox] Ability to control the sizing of the overflown content area #8725

Open
kizu opened this issue Apr 14, 2023 · 8 comments

Comments

@kizu
Copy link
Member

kizu commented Apr 14, 2023

I did recently stumbled upon some weirdness regarding how flex and overflow interact.

I could not find an issue that would talk about it, and couldn't find the exact place in the specs that describe this interaction, so would be helpful for any directions!

Disclaimer: this might be also the case for display: grid, I did not thoroughly tested anything other than display: flex for now.

References:

The problem:

  • When we have a container that has both display: flex and a non-visible overflow (my exact case was with overflow: auto), we do not have any control on how the inner content box of the overflowing container is sized, resulting in content always shrinking up to the items' respective min intrinsic sizes:

    Screen.Recording.2023-04-14.at.21.19.44.mov
  • What I want to have, achivable, for example, if we would instead move the flex container inside the container with the overflow — we get control over how it would behave via min-width or height: the container is sized to fit all the items:

    Screen.Recording.2023-04-14.at.21.20.18.mov

My proposal:

  • Add a CSS property (or multiple?) that would control how the content area of the overflowing container should be sized.

Current workarounds:

  1. The already mentioned separation of the overflow and flex — allows achieving both cases: when we want things to shrink, or not.
  2. Using .flex > * { flex-shrink: 0; } — kinda works, but only for the start value of the justify-content property, otherwise things behave not in a desired way.
@Loirooriol
Copy link
Contributor

The other items work as desired thanks to min-width: auto; min-height: auto, which behave somewhat like min-content for them, but behave as 0 with overflow: hidden.

So you should be able to just add .item.oh { min-width: min-content; min-height: min-content }. No need to change the HTML structure as you seem to assume?

The only problem is that browsers still treat min-content as auto in the block axis. So it doesn't work in the column case. But the solution is that browsers need to obey #3973, we don't need new properties.

Also, consider overflow: clip instead of hidden, since it doesn't trigger a scroll container.

@kizu
Copy link
Member Author

kizu commented Apr 15, 2023

So you should be able to just add .item.oh { min-width: min-content; min-height: min-content }. No need to change the HTML structure as you seem to assume?

The problem is not to handle things on the children, but control this on the parent. If we would think of the elements as isolated components, then we need to be able to make the parent container not shrink children regardless of what styles are on them.

We can achieve this with 2 wrappers — top one with the overflow, and the one inside with flex, but we cannot achieve this with only one wrapper — this is the problem.

Also, consider overflow: clip instead of hidden

Can you elaborate? I've tried it on the .oh, and it didn't change anything for me. And this also means modifying a child, while the goal is to make the parent work correctly.

The only problem is that browsers still treat min-content as auto in the block axis. So it doesn't work in the column case.

The column case is what I actually have in practice, in the product code where we stumbled upon this :)

And, lastly, even if all children would not get shrunk (see the case where we add the flex-shrink to all of them), we would be left with the issue of justify-content, where if we'd want to set it to center (or to almost any other value), we'd get things clipped over the start of the container due to it only considering the width of it for where to place them.

@Loirooriol
Copy link
Contributor

The problem is not to handle things on the children, but control this on the parent.

It's the children who opt out of the default behavior by becoming scroll containers, so it's up to them to mitigate the negative effects.

Can you elaborate? I've tried it on the .oh, and it didn't change anything for me.

https://software.hixie.ch/utilities/js/live-dom-viewer/saved/11533 Try Firefox. It seems Chrome has a bug.

And this also means modifying a child

I don't get it, why can you set overflow: hidden on a child but you can't set overflow: clip on a child?

we would be left with the issue of justify-content

That's by design, you want safe center instead of center. https://drafts.csswg.org/css-align-3/#overflow-values

@kizu
Copy link
Member Author

kizu commented Apr 15, 2023

It's the children who opt out of the default behavior by becoming scroll containers, so it's up to them to mitigate the negative effects.

This is not really applicable to some of the real-world use-cases, where different teams can work on different components, and a design system needs to provide a component that is resilient and can accommodate whatever is thrown into it — in this case the component would need to be split in two elements. So, the limitation of CSS leads to a bloated HTML.

I don't get it, why can you set overflow: hidden on a child but you can't set overflow: clip on a child?

See above — a component would not know what exactly would be placed into it, and the child won't know in which container it would be placed. We could argue, that in that case the component shouldn't have the display: flex on it, but then that would mean that in case we'd want to add a flex layout inside, we'd have to still use an extra wrapper to separate the overflow from flex.

Try Firefox. It seems Chrome has a bug

Oh, interesting! Safari has the same bug, so I would need to look into if it exists in their bug trackers.

That's by design, you want safe center instead of center. https://drafts.csswg.org/css-align-3/#overflow-values

TIL, though, a bit sad that it works only in Firefox for now. And, maybe you know — is it intended not to work with space-around or space-around values, or is it a Firefox bug?

@Loirooriol
Copy link
Contributor

is it intended not to work with space-around or space-around values

It works with <content-position>, not with <content-distribution>. These have a fallback alignment, which currently can't be customized. See https://drafts.csswg.org/css-align-3/#distribution-values

When space cannot be distributed in this way, these values behave as their fallback alignment. Each distribution value has an associated default fallback alignment. (A future level of this module may allow the fallback alignment to be specified explicitly.)

So space-between falls back to start and doesn't overflow on the start side. space-around and space-evenly should now fall back to safe center (#5088), but browsers still use center.

@kizu
Copy link
Member Author

kizu commented Apr 15, 2023

Ah, nice, the fallback alignment sounds good. Can't wait for all of that to be available — it + > * { flex-shrink: 0 } should mostly work, but — I still think that this should be possible to specify on the element itself.

My opinion — almost every time there is something that makes sense to specified as > * should be possible via setting something on the element itself. That's how we got the gap instead of all the margins, that's one of my things in a wish-list for CSS grids (ability to specify default columns/rows for example), and in this case this is also something that, imho, makes sense to have as a container property. There are too many reasons not to rely on the > *, like the specificity clashes, inability to set it via JS without overcomplicated code, and so on.

Edit: To add to the above — another reason why > * is not a general solution for “defaults” is if we'd want to use a CSS variable value there, as we then couldn't redefine the value on it without #2864, so we would require the support for inherited if we'd want to make the value of that flex-shrink dynamic. Possible case: implementing conditional responsive logic with CSS variables.

@Loirooriol
Copy link
Contributor

I guess flex-grow-items and flex-shrink-items properties on a flex container that would set the default values for the items might have been interesting. But now it would require changing the initial value of flex-grow and flex-shrink, which may be risky.

@kizu
Copy link
Member Author

kizu commented Apr 17, 2023

Hmm, yes, I imagine that in that case it would need to be “auto” which computes to the parent's -items value if present and 1 otherwise. I can see how changing the default can be challenging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants