Skip to content

[css-sizing][css-flexbox] It's false that stretch size behaves as stretch alignment #11784

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

Open
Loirooriol opened this issue Feb 26, 2025 · 11 comments

Comments

@Loirooriol
Copy link
Contributor

Loirooriol commented Feb 26, 2025

https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing

We have interoperability against this:

<!DOCTYPE html>
<style>
.container { display: inline-flex; vertical-align: top; width: 100px; height: 100px; border: solid; flex-wrap: wrap; align-content: start }
.stretch { height: -moz-available; height: -webkit-fill-available; height: stretch }
</style>
<div class="container">
  <div class="stretch" style="width: 75px; border: solid cyan">a</div>
  <div class="stretch" style="width: 75px; border: solid magenta">b</div>
</div>
<div class="container">
  <div class="stretch" style="width: 75px; border: solid cyan">a</div>
  <div style="border: solid orange; height: 150px"></div>
  <div class="stretch" style="width: 75px; border: solid magenta">b</div>
</div>
<div class="container">
  <div style="width: 75px; border: solid cyan;">a</div>
  <div style="width: 75px; border: solid magenta">b</div>
</div>
<div class="container">
  <div style="width: 75px; border: solid cyan;">a</div>
  <div style="border: solid orange; height: 150px"></div>
  <div style="width: 75px; border: solid magenta">b</div>
</div>

Gecko, Blink and WebKit agree:

  • When computing the size of the flex lines: height: stretch stretches against the containing block, while align-self: stretch doesn't stretch.
  • Once we know the size of the flex lines: height: stretch keeps stretching against the containing block, while align-self: stretch stretches against the line.

If the flex container doesn't have a definite height (remove height: 100px):

  • Gecko and Blink don't stretch height: stretch, neither when computing line sizes nor once we know their size. align-self stretches in the latter one:

  • WebKit does that thing of stretching all ancestors with indefinite size, in this case filling the window:

@Loirooriol
Copy link
Contributor Author

BTW, same for a column flexbox:

<!DOCTYPE html>
<style>
.container { display: flex; flex-direction: column; width: 100px; height: 100px; border: solid; flex-wrap: wrap; align-content: start }
.stretch { width: -moz-available; width: -webkit-fill-available; width: stretch }
</style>
<div class="container">
  <div class="stretch" style="height: 75px; border: solid cyan">a</div>
  <div class="stretch" style="height: 75px; border: solid magenta">b</div>
</div>
<div class="container">
  <div class="stretch" style="height: 75px; border: solid cyan">a</div>
  <div style="border: solid orange; width: 150px"></div>
  <div class="stretch" style="height: 75px; border: solid magenta">b</div>
</div>
<div class="container">
  <div style="height: 75px; border: solid cyan;">a</div>
  <div style="height: 75px; border: solid magenta">b</div>
</div>
<div class="container">
  <div style="height: 75px; border: solid cyan;">a</div>
  <div style="border: solid orange; width: 150px"></div>
  <div style="height: 75px; border: solid magenta">b</div>
</div>

With width: min-content; max-width: 100px:

@Loirooriol Loirooriol changed the title [css-sizing] It's false that height: stretch behaves as stretch alignment [css-sizing][css-flexbox] It's false that height: stretch behaves as stretch alignment Mar 10, 2025
@Loirooriol
Copy link
Contributor Author

Maybe I could have merged this into #11293. But this one is more about flexbox, that one about abspos.

@tabatkins
Copy link
Member

I chatted with @bfgeek about this today.

Currently our behavior for flex items is to treat width/height:stretch as equivalent to width/height:100%, rather than equivalent to stretch alignment. This equivalency is correct in most other places, but differs here, as you point out. However, the equivalency is also broken in abspos, where %s resolve against the original CB size but stretch alignment (and width:auto) resolves against the IMCB; Chrome implements width/height:stretch to fill the IMCB, matching stretch alignment.

So, I'm inclined to say we should try and follow the spec's text. It's consistent with the behavior in all other locations, afaik, and presents a more useful behavior for this case. It does mean widening the delta between stretch and -webkit-fill-available, so there's potentially some compat risk, but I'd like to try for it if possible.

However, if it turns out this is an issue, I'm okay with resolving to match the 100% behavior in this case instead.

@Loirooriol
Copy link
Contributor Author

Note that making a stretch size match stretch alignment presumably means that fit-content should also stretch to the line, but clamping between min-content and max-content. This might introduce some compat risk, but probably fine.

Chrome implements width/height:stretch to fill the IMCB, matching stretch alignment.

False, see #11293

@Loirooriol Loirooriol changed the title [css-sizing][css-flexbox] It's false that height: stretch behaves as stretch alignment [css-sizing][css-flexbox] It's false that stretch size behaves as stretch alignment Mar 18, 2025
@astearns astearns moved this to Regular agenda in CSSWG April 2025 meeting agenda Mar 27, 2025
@davidsgrogan
Copy link
Member

Heads up @dholbert , this issue is talking about changing stretch in the cross axis direction so that it resolves to the flex line's available space, not to the flex container's available space. If we do this, it would directly contradict your test assertion at https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/web_tests/external/wpt/css/css-sizing/stretch/stretch-block-size-001.html;l=189-191;drc=910dc12bbc0595ea727c435b8298998ccc53e965

WDYT?

@dholbert
Copy link
Member

Thanks for the heads-up! No concerns from me on changing that testcase's expectations.

When I wrote that test, I don't think I was aware of the linked spec text (the text that gives stretch sizes special meaning in contexts where *-self alignment applies), and I was just thinking of stretch as being a fancy 100% similar to how @tabatkins described it above.

@bfgeek
Copy link

bfgeek commented Apr 25, 2025

So while experimenting with implementing this we've come to the conclusion that its not true that align-self: stretch and width: stretch are always equal.

Specifically the difference comes from:

Determine the hypothetical cross size of each item by performing layout as if it were an in-flow block-level box with the used main size and the given available space, treating auto as fit-content.

https://drafts.csswg.org/css-flexbox-1/#algo-cross-item

For example:

<!DOCTYPE html>
<div style="font: 16px monospace; width: 100px; height: 100px; border: solid 4px; display: flex; gap: 10px; flex-wrap: wrap; flex-direction: column;">
  <div style="background: lime;">a b c </div>
  <div style="background: lime;">a b c d e f g h i j k l m n o p q r s t u v w x y z</div>
</div>

https://www.software.hixie.ch/utilities/js/live-dom-viewer/?saved=13715

When determining the line-cross-size of a wrapping flexbox (typically of a column flexbox) the given available-size is always the container available size.

In this stage width: auto becomes width: fit-content. The line-cross-size is calculated based on this fact.

Then when determining the final used cross size (the final layout of the flex-item) width: auto becomes width: stretch.
This comes from:

Determine the used cross size of each flex item. If a flex item has align-self: stretch, its computed cross size property is auto, and neither of its cross-axis margins are auto, the used outer cross size is the used cross size of its flex line, clamped according to the item’s used min and max cross sizes. Otherwise, the used cross size is the item’s hypothetical cross size.

https://drafts.csswg.org/css-flexbox-1/#algo-stretch

width: stretch doesn't have the ability to change, and hence can result in a different layout in these circumstances.

IMO I think this behaviour difference is fine/expected. I don't think we want to magically coerce stretch to fit-content in the cross-size determination step.

(Also note that passing an indefinite available size doesn't work as that'll make the width max-content instead of fit-content which is a sutble behaviour difference).

I think that then the part of the sizing spec:

Produces the same size that would be obtained by the self-alignment property in that axis being set to stretch and all sizing properties and aspect-ratio being set to their initial values.

https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing

... is mostly true, but incorrect when it comes to flexbox for the above reason. (There are larger implications for any behaviour change away from this when we have things like min-width: stretch; width: fit-content for example).

@davidsgrogan
Copy link
Member

In recent chrome canary we changed stretch to behave closer to align-self: stretch. Blink now mostly stretches cross-size:stretch to the line, not the container. But we arguably* don't completely follow the current spec, and think it's better behavior not to, as @bfgeek mentions above.

Our deviation from the current spec (and, as a corollary, our spec-change proposal) can be summed up as

  • If flex-line cross size is known, cross-size:stretch stretches to it
  • Otherwise (e.g. when computing the flex-line cross-size), cross-size:stretch stretches to the container width

Whereas the current spec arguably* requires

  • If flex-line cross size is known, cross-size:stretch stretches to it
  • Otherwise, cross-size:stretch behaves as fit-content with container cross size as available size

Revisiting Oriol's example in #11784 (comment): (live):

<!DOCTYPE html>
<style>
.container { display: flex; flex-direction: column; width: 100px; height: 100px; border: solid; flex-wrap: wrap; align-content: start }
.stretch { width: -moz-available; width: -webkit-fill-available; width: stretch }
</style>
<div class="container">
  <div class="stretch" style="height: 75px; border: solid cyan">a</div>
  <div class="stretch" style="height: 75px; border: solid magenta">b</div>
</div>
<div class="container">
  <div class="stretch" style="height: 75px; border: solid cyan">a</div>
  <div style="border: solid orange; width: 150px"></div>
  <div class="stretch" style="height: 75px; border: solid magenta">b</div>
</div>
<div class="container">
  <div style="height: 75px; border: solid cyan;">a</div>
  <div style="height: 75px; border: solid magenta">b</div>
</div>
<div class="container">
  <div style="height: 75px; border: solid cyan;">a</div>
  <div style="border: solid orange; width: 150px"></div>
  <div style="height: 75px; border: solid magenta">b</div>
</div>

Blink's old behavior:
Image
Blink's new behavior:
Image
What the spec arguably* calls for:
Image

In some of these flex items, the author asked to stretch, and the current spec arguably* says to match align-self:stretch, but that results in no stretching at all. We argue that not stretching when the author requested it is lame; we should give them some version of what they want when we can.

@dholbert @Loirooriol WDYT? Do you prefer Blink's "new" behavior, or the "spec" behavior?

PS: On mentions of arguably*: I say arguably, because there's actually an interpretation of the spec that dictates our proposed behavior already. Namely, emphasis added,

If used in an axis where the relevant self-alignment property applies to the element

Produces the same size that would be obtained by the self-alignment property in that axis being set to stretch and all sizing properties and aspect-ratio being set to their initial values.

Otherwise, if used in an axis where percentage sizes can resolve to a definite value

Behaves as 100%, except it sizes the margin box regardless of the value of box-sizing.

When we are calculating the the flex-line cross-size, align-self doesn't apply! So we follow the 'Otherwise' 100% behavior. When we do so, the line ends up being the same width as the container, which has the same effect of stretching to the container in the end.

@davidsgrogan
Copy link
Member

@dholbert @Loirooriol We're looking to solidify cross-size:stretch behavior in flexbox. Following up on my question from a weeks ago (#11784 (comment)) regarding Blink's proposed "new" behavior versus the current spec interpretation:

Do either of you have a preference or concerns with the "new" behavior described? Your insights are always helpful!

@dholbert
Copy link
Member

@davidsgrogan Hi! Sorry for delayed response. I think your proposed change (the "new behavior") makes sense; and I agree with the case you make in your footnote that it arguably already is what the spec is already asking for.

@Loirooriol
Copy link
Contributor Author

I don't have a strong opinion, I'm also fine with the original browser behavior. I will give a try to implement one of the new behaviors in Servo in case it adds some unwanted complexity.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue May 20, 2025
This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
aarongable pushed a commit to chromium/chromium that referenced this issue May 20, 2025
This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6569793
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1463062}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue May 20, 2025
This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6569793
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1463062}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue May 20, 2025
This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6569793
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1463062}
lando-prod-mozilla bot pushed a commit to mozilla-firefox/firefox that referenced this issue May 23, 2025
…ew indefinite behavior,

Automatic update from web-platform-tests
[flex] Update stretch tests to reflect new indefinite behavior

This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6569793
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1463062}

--

wpt-commits: 4a9adb8c2eb1801445c7b281311447f22ec432c7
wpt-pr: 52674

Differential Revision: https://phabricator.services.mozilla.com/D250955
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue May 24, 2025
…ew indefinite behavior,

Automatic update from web-platform-tests
[flex] Update stretch tests to reflect new indefinite behavior

This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6569793
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1463062}

--

wpt-commits: 4a9adb8c2eb1801445c7b281311447f22ec432c7
wpt-pr: 52674

Differential Revision: https://phabricator.services.mozilla.com/D250955
i3roly pushed a commit to i3roly/firefox-dynasty that referenced this issue May 26, 2025
…ew indefinite behavior,

Automatic update from web-platform-tests
[flex] Update stretch tests to reflect new indefinite behavior

This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6569793
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1463062}

--

wpt-commits: 4a9adb8c2eb1801445c7b281311447f22ec432c7
wpt-pr: 52674

Differential Revision: https://phabricator.services.mozilla.com/D250955
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this issue May 28, 2025
…ew indefinite behavior,

Automatic update from web-platform-tests
[flex] Update stretch tests to reflect new indefinite behavior

This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6569793
Reviewed-by: Ian Kilpatrick <ikilpatrickchromium.org>
Commit-Queue: David Grogan <dgroganchromium.org>
Cr-Commit-Position: refs/heads/main{#1463062}

--

wpt-commits: 4a9adb8c2eb1801445c7b281311447f22ec432c7
wpt-pr: 52674

Differential Revision: https://phabricator.services.mozilla.com/D250955

UltraBlame original commit: 2443ea23af2704db221a0c693ab93b36f4fdf479
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this issue May 28, 2025
…ew indefinite behavior,

Automatic update from web-platform-tests
[flex] Update stretch tests to reflect new indefinite behavior

This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6569793
Reviewed-by: Ian Kilpatrick <ikilpatrickchromium.org>
Commit-Queue: David Grogan <dgroganchromium.org>
Cr-Commit-Position: refs/heads/main{#1463062}

--

wpt-commits: 4a9adb8c2eb1801445c7b281311447f22ec432c7
wpt-pr: 52674

Differential Revision: https://phabricator.services.mozilla.com/D250955

UltraBlame original commit: 2443ea23af2704db221a0c693ab93b36f4fdf479
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this issue May 28, 2025
…ew indefinite behavior,

Automatic update from web-platform-tests
[flex] Update stretch tests to reflect new indefinite behavior

This is the behavior described in
w3c/csswg-drafts#11784 (comment)
and the following comment.

Change-Id: Ie3fd71de25a3e35d73d52be7152bab3ba8823320
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6569793
Reviewed-by: Ian Kilpatrick <ikilpatrickchromium.org>
Commit-Queue: David Grogan <dgroganchromium.org>
Cr-Commit-Position: refs/heads/main{#1463062}

--

wpt-commits: 4a9adb8c2eb1801445c7b281311447f22ec432c7
wpt-pr: 52674

Differential Revision: https://phabricator.services.mozilla.com/D250955

UltraBlame original commit: 2443ea23af2704db221a0c693ab93b36f4fdf479
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Regular agenda
Development

No branches or pull requests

5 participants