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-4] How does height: stretch interact with margin collapsing with parent #11044

Closed
dbaron opened this issue Oct 17, 2024 · 44 comments
Closed

Comments

@dbaron
Copy link
Member

dbaron commented Oct 17, 2024

There were some possibly-related previous discussions in #923 and #1614.

The definition of stretch-fit sizing says:

Additionally, in formatting contexts and axes in which the relevant self-alignment property does not apply (such as the block axis in Block Layout, or the main axis in Flex Layout), in cases where a percentage size in that axis would resolve to a definite value, a stretch-fit size causes the box to attempt to fill its containing block—​behaving as 100% but applying the resulting size to its margin box instead of the box indicated by box-sizing. For this purpose, auto margins are treated as zero, and furthermore, for block-level boxes in particular, if its block-start/block-end margin would be adjoining to its parent’s block-start/block-end margin if its parent’s sizing properties all had their initial values, then its block-start/block-end margin is treated as zero.

It's not clear to me if this last sentence that says the margin is treated as zero is also intended to imply that there are revisions to the margin collapsing rules that make the margin show up on the parent. (I don't know of any version of the margin collapsing rules other than the one in CSS 2.1.) At first glance it seems like this might make sense. However, it doesn't make much sense in the case where this element has siblings. In particular:

  • The sizing rule given here sizes the element as though it has no siblings. But it might, in fact, have siblings. (But making stretch behave "correctly" when there are siblings might be something we don't really want to do -- it's certainly difficult, particularly when more than one element has stretch.)
  • The current spec definition of margin-collapsing is intentionally asymmetric: blocks with a non-auto height do not collapse their end margin with their last child. If this is intended to change that in some cases, it should probably be more explicit about it. This spec text introduces a hypothetical "if its parent's sizing properties all had their initial values" to explicitly avoid that rule, but as a result it makes a margin disappear that doesn't end up anywhere else.
  • If the goal were to have margins collapse if the stretch sizes the children to exactly fit the parent, it seems like the special collapsing rules should only apply when there aren't siblings to mess up the sizing, or something like that.

It's not clear to me why it's desirable to make these margins disappear given the current rules for handling siblings and margin collapsing. It seems like a straightforward fix would be to remove the special rule about zeroing margins for block-level boxes. Why don't we want to just allow the normal rules to run and size the element using its margins?

Or was there an intention that siblings and/or margin collapsing be handled differently?

@Loirooriol
Copy link
Contributor

Quick test: https://software.hixie.ch/utilities/js/live-dom-viewer/saved/13208

<!DOCTYPE html>
<style>.stretch { height: -moz-available; height: -webkit-fill-available; height: stretch }</style>
<div style="outline: solid; height: 100px; width: 100px">
  <div class="stretch" style="margin: 10px; border: solid magenta"></div>
</div>
<br>
<div style="outline: solid; height: 100px; width: 100px">
  <div style="overflow: hidden"></div>
  <div class="stretch" style="margin: 10px; border: solid cyan"></div>
  <div style="overflow: hidden"></div>
</div>
Gecko Blink WebKit

I think the spec says that magenta should be like WebKit, and cyan like Blink, which is what looks the best to me.

@dbaron
Copy link
Member Author

dbaron commented Oct 17, 2024

It's not completely clear to me why we want to ignore the margin on the magenta test, though. Is it really correct that the margin should just disappear? Or should we at least expect the top margin to get collapsed to the outside of the parent? (And does it then make sense to ignore the bottom margin to get some symmetry -- but not full symmetry -- since we don't want to change the margin collapsing rules too much?)

@Loirooriol
Copy link
Contributor

Yes, the top margin collapses as normal, the bottom one doesn't (because of height: 100px) but it looks like collapsing.

@Loirooriol
Copy link
Contributor

Maybe it's clearer like

<!DOCTYPE html>
<style>.stretch { height: -moz-available; height: -webkit-fill-available; height: stretch }</style>
⬇️ margin here
<div style="outline: solid; height: 100px; width: 100px">
  <div class="stretch" style="margin: 30px; border: solid magenta"></div>
</div>
⬆️ no margin here

The bottom margin should just be considered as collapsing with the parent for the purpose of resolving stretch. But then it doesn't actually collapse, it just overflows.

aarongable pushed a commit to chromium/chromium that referenced this issue Oct 17, 2024
One of our goals is for `-webkit-fill-available` and `stretch`
to have identical layout behavior.

Feature is not yet ready to ship.

Remaining work:
 * support stretch in flex-basis
 * add abspos tests with one inset specified
 * add aspect ratio test and fix if necessary
 * ditto with fixed table layout as mentioned in
   w3c/csswg-drafts#4028 (comment)
 * serialization?
 * Test that auto margins are treated as 0
 * fix block-height-2.html behavior and/or decide to change the spec
 * Add margin tests and fix our behavior for the cases discussed in
   w3c/csswg-drafts#11044

Change-Id: I8c773eb3fe964e58877e0d7d8dbb6325580e0cda
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884393
Reviewed-by: David Baron <dbaron@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1370209}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 17, 2024
One of our goals is for `-webkit-fill-available` and `stretch`
to have identical layout behavior.

Feature is not yet ready to ship.

Remaining work:
 * support stretch in flex-basis
 * add abspos tests with one inset specified
 * add aspect ratio test and fix if necessary
 * ditto with fixed table layout as mentioned in
   w3c/csswg-drafts#4028 (comment)
 * serialization?
 * Test that auto margins are treated as 0
 * fix block-height-2.html behavior and/or decide to change the spec
 * Add margin tests and fix our behavior for the cases discussed in
   w3c/csswg-drafts#11044

Change-Id: I8c773eb3fe964e58877e0d7d8dbb6325580e0cda
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884393
Reviewed-by: David Baron <dbaron@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1370209}
@dbaron
Copy link
Member Author

dbaron commented Oct 17, 2024

I guess I thought the margin gets treated as zero, and doesn't get treated as collapsing. But now I think actually the spec is unclear, because it's not clear if the "and furthermore" part of the sentence is still within the scope of the "For this purpose" earlier in the sentence, or if the "and" escapes that scope. That is, it's not clear if the sentence is structured as "(For this purpose, X), and furthermore, Y." or "For this purpose, (X, and furthermore, Y).".

(I should also mention that this issue came out of a code review discussion.)

@Loirooriol
Copy link
Contributor

I think it's the latter, the former seems weird.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 17, 2024
One of our goals is for `-webkit-fill-available` and `stretch`
to have identical layout behavior.

Feature is not yet ready to ship.

Remaining work:
 * support stretch in flex-basis
 * add abspos tests with one inset specified
 * add aspect ratio test and fix if necessary
 * ditto with fixed table layout as mentioned in
   w3c/csswg-drafts#4028 (comment)
 * serialization?
 * Test that auto margins are treated as 0
 * fix block-height-2.html behavior and/or decide to change the spec
 * Add margin tests and fix our behavior for the cases discussed in
   w3c/csswg-drafts#11044

Change-Id: I8c773eb3fe964e58877e0d7d8dbb6325580e0cda
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884393
Reviewed-by: David Baron <dbaron@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1370209}
@bfgeek
Copy link

bfgeek commented Oct 17, 2024

Some practical constraints from an engine perspective.
Blink doesn't know anything about any proceeding margins, e.g.

<div style="height: stretch; margin-bottom: 10px"></div>
<div style="margin-bottom: 20px;"></div>
content

(Blink at the time of giving the first div a height, doesn't know about the 20px margin).
This is a simple case, but the end margins can come from an arbitrary sibling, and we really don't want to break this invariant.

From a simplicity of implementation POV ignoring margins entirely might be an option.

A tradeoff which might be acceptable is to consider the elements (own) margins if the element is a direct child of a BFC. But from an implementation simplicity POV ignore collapsing e.g.

<div style="display: root; height: 100px;">
  <div style="margin: 10px; height: stretch;"></div>
</div>

Then for the case where the child has a non-BFC parent ignore the margins.

Also note that we are somewhat compat constrained if we want to keep stretch as a pure alias of -webkit-fill-available.

Ian

@Loirooriol
Copy link
Contributor

we are somewhat compat constrained if we want to keep stretch as a pure alias of -webkit-fill-available

Blink and WebKit have different behaviors, so it's probably fine if we choose one or the other depending on the case.

Blink doesn't know anything about any proceeding margins

In Servo we parallelize block layout (when there are no floats), so we also have this problem for preceding margins.

ignoring margins entirely might be an option

Do you mean to just stretch the border box like WebKit? This can result in overflow if the margins don't end up collapsing, which seems bad.

consider the elements (own) margins if the element is a direct child of a BFC

I think that ignoring margins for non-BFC parent is too restrictive.

So I have another proposal. Given that:

  • stretch doesn't make that much sense if there are siblings
  • Margins collapsing through boxes was a mistake and "the root of all margin-collapsing evil".
  • In case of doubt, it seems better to not overflow

Then we could, for the purpose of resolving a vertical stretch on a block-level box:

  • Treat the top margin as 0 if the box has no preceding sibling, and the top margin is adjoining with the top margin of its parent
  • Treat the bottom margin as 0 if the box has no following sibling, and the bottom margin would be adjoining with the bottom margin of its parent if the parent’s sizing properties all had their initial values.

For the purpose of checking preceding/following siblings, ignore collapsed whitespace and out-of-flow elements.

So then I think we only need to check:

  • Whether the parent establishes an independent BFC
  • Whether the parent has vertical borders or padding
  • Whether our element has clearance (only for the top margin)
  • Whether our element is the first/last child

Seems fine from an implementation POV.

moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Oct 21, 2024
…idth/height, a=testonly

Automatic update from web-platform-tests
[layout] Accept 'stretch' keyword as a width/height

One of our goals is for `-webkit-fill-available` and `stretch`
to have identical layout behavior.

Feature is not yet ready to ship.

Remaining work:
 * support stretch in flex-basis
 * add abspos tests with one inset specified
 * add aspect ratio test and fix if necessary
 * ditto with fixed table layout as mentioned in
   w3c/csswg-drafts#4028 (comment)
 * serialization?
 * Test that auto margins are treated as 0
 * fix block-height-2.html behavior and/or decide to change the spec
 * Add margin tests and fix our behavior for the cases discussed in
   w3c/csswg-drafts#11044

Change-Id: I8c773eb3fe964e58877e0d7d8dbb6325580e0cda
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884393
Reviewed-by: David Baron <dbaron@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1370209}

--

wpt-commits: 9356370c840aabd208b5460fb11efaab8b4f94e6
wpt-pr: 48680
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this issue Oct 22, 2024
…idth/height, a=testonly

Automatic update from web-platform-tests
[layout] Accept 'stretch' keyword as a width/height

One of our goals is for `-webkit-fill-available` and `stretch`
to have identical layout behavior.

Feature is not yet ready to ship.

Remaining work:
 * support stretch in flex-basis
 * add abspos tests with one inset specified
 * add aspect ratio test and fix if necessary
 * ditto with fixed table layout as mentioned in
   w3c/csswg-drafts#4028 (comment)
 * serialization?
 * Test that auto margins are treated as 0
 * fix block-height-2.html behavior and/or decide to change the spec
 * Add margin tests and fix our behavior for the cases discussed in
   w3c/csswg-drafts#11044

Change-Id: I8c773eb3fe964e58877e0d7d8dbb6325580e0cda
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884393
Reviewed-by: David Baron <dbaronchromium.org>
Commit-Queue: David Grogan <dgroganchromium.org>
Cr-Commit-Position: refs/heads/main{#1370209}

--

wpt-commits: 9356370c840aabd208b5460fb11efaab8b4f94e6
wpt-pr: 48680

UltraBlame original commit: 22a10cdf4ad6356ec9dfd4fc78e2c3c71770eca7
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this issue Oct 22, 2024
…idth/height, a=testonly

Automatic update from web-platform-tests
[layout] Accept 'stretch' keyword as a width/height

One of our goals is for `-webkit-fill-available` and `stretch`
to have identical layout behavior.

Feature is not yet ready to ship.

Remaining work:
 * support stretch in flex-basis
 * add abspos tests with one inset specified
 * add aspect ratio test and fix if necessary
 * ditto with fixed table layout as mentioned in
   w3c/csswg-drafts#4028 (comment)
 * serialization?
 * Test that auto margins are treated as 0
 * fix block-height-2.html behavior and/or decide to change the spec
 * Add margin tests and fix our behavior for the cases discussed in
   w3c/csswg-drafts#11044

Change-Id: I8c773eb3fe964e58877e0d7d8dbb6325580e0cda
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884393
Reviewed-by: David Baron <dbaronchromium.org>
Commit-Queue: David Grogan <dgroganchromium.org>
Cr-Commit-Position: refs/heads/main{#1370209}

--

wpt-commits: 9356370c840aabd208b5460fb11efaab8b4f94e6
wpt-pr: 48680

UltraBlame original commit: 22a10cdf4ad6356ec9dfd4fc78e2c3c71770eca7
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this issue Oct 22, 2024
…idth/height, a=testonly

Automatic update from web-platform-tests
[layout] Accept 'stretch' keyword as a width/height

One of our goals is for `-webkit-fill-available` and `stretch`
to have identical layout behavior.

Feature is not yet ready to ship.

Remaining work:
 * support stretch in flex-basis
 * add abspos tests with one inset specified
 * add aspect ratio test and fix if necessary
 * ditto with fixed table layout as mentioned in
   w3c/csswg-drafts#4028 (comment)
 * serialization?
 * Test that auto margins are treated as 0
 * fix block-height-2.html behavior and/or decide to change the spec
 * Add margin tests and fix our behavior for the cases discussed in
   w3c/csswg-drafts#11044

Change-Id: I8c773eb3fe964e58877e0d7d8dbb6325580e0cda
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884393
Reviewed-by: David Baron <dbaronchromium.org>
Commit-Queue: David Grogan <dgroganchromium.org>
Cr-Commit-Position: refs/heads/main{#1370209}

--

wpt-commits: 9356370c840aabd208b5460fb11efaab8b4f94e6
wpt-pr: 48680

UltraBlame original commit: 22a10cdf4ad6356ec9dfd4fc78e2c3c71770eca7
ErichDonGubler pushed a commit to erichdongubler-mozilla/firefox that referenced this issue Oct 23, 2024
…idth/height, a=testonly

Automatic update from web-platform-tests
[layout] Accept 'stretch' keyword as a width/height

One of our goals is for `-webkit-fill-available` and `stretch`
to have identical layout behavior.

Feature is not yet ready to ship.

Remaining work:
 * support stretch in flex-basis
 * add abspos tests with one inset specified
 * add aspect ratio test and fix if necessary
 * ditto with fixed table layout as mentioned in
   w3c/csswg-drafts#4028 (comment)
 * serialization?
 * Test that auto margins are treated as 0
 * fix block-height-2.html behavior and/or decide to change the spec
 * Add margin tests and fix our behavior for the cases discussed in
   w3c/csswg-drafts#11044

Change-Id: I8c773eb3fe964e58877e0d7d8dbb6325580e0cda
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884393
Reviewed-by: David Baron <dbaron@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1370209}

--

wpt-commits: 9356370c840aabd208b5460fb11efaab8b4f94e6
wpt-pr: 48680
i3roly pushed a commit to i3roly/firefox-dynasty that referenced this issue Oct 24, 2024
…idth/height, a=testonly

Automatic update from web-platform-tests
[layout] Accept 'stretch' keyword as a width/height

One of our goals is for `-webkit-fill-available` and `stretch`
to have identical layout behavior.

Feature is not yet ready to ship.

Remaining work:
 * support stretch in flex-basis
 * add abspos tests with one inset specified
 * add aspect ratio test and fix if necessary
 * ditto with fixed table layout as mentioned in
   w3c/csswg-drafts#4028 (comment)
 * serialization?
 * Test that auto margins are treated as 0
 * fix block-height-2.html behavior and/or decide to change the spec
 * Add margin tests and fix our behavior for the cases discussed in
   w3c/csswg-drafts#11044

Change-Id: I8c773eb3fe964e58877e0d7d8dbb6325580e0cda
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5884393
Reviewed-by: David Baron <dbaron@chromium.org>
Commit-Queue: David Grogan <dgrogan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1370209}

--

wpt-commits: 9356370c840aabd208b5460fb11efaab8b4f94e6
wpt-pr: 48680
@tabatkins
Copy link
Member

Starting from the OP; I'll respond to further comments after.

First, we definitely don't care about siblings. We wrote these rules on the assumption that the stretched chidl is the sole content; if that's not the case, it might give suboptimal results, but you should be using Flexbox in that case anyway.

We also, I'm pretty sure intentionally, are not changing margin collapse behavior in any way. Margin collapse is complicated and we didn't want to touch it. All we say is that, if the margin is adjoining with its parents (and, for bottom margins, pretend the parent isn't using a sizing value that would prevent adjoinment), then for the purpose of sizing the child its margins are truncated to zero.

If, independent of that, the child's margins are adjoining either of the parent's margins, according to the standard rules, then they collapse as normal. This means that a sole child using 'stretch', inside of a fixed-size parent, will automatically be flush with both the top and bottom of the parent, and its top margin will be collapsing with the parent as normal; its bottom margin is simply ignored.

@fantasai, does this sound right? It's been a while since we last worked on this section.


I think the spec says that magenta should be like WebKit, and cyan like Blink, which is what looks the best to me.

Correct, that's the spec's intention. Additionally, in the magenta case, the child's top margin will have collapsed with the parent's, so the parent will effectively have a 10px top margin. The example in #11044 (comment) is also correct.


That is, it's not clear if the sentence is structured as "(For this purpose, X), and furthermore, Y." or "For this purpose, (X, and furthermore, Y).".

As Oriol suggests, it's the latter. On a reread, it did take me a second to parse, tho, so I do think we should rewrite that a little.

@Loirooriol
Copy link
Contributor

We wrote these rules on the assumption that the stretched chidl is the sole content; if that's not the case, it might give suboptimal results

The problem isn't that it's suboptimal, it's that Blink and Servo don't know whether the margins are adjoining at the time that they resolve stretch.

So IMO we can either assume that there is no sibling, or assume that if there are siblings they don't collapse thru. The latter seems better to avoid overflow if the assumption is wrong.

@davidsgrogan
Copy link
Member

I interpreted Tab's response to mean "assume that there is no sibling", FWIW.

But Oriol, can you give an example and expected behavior if we go with "assume siblings don't collapse through"?

@Loirooriol
Copy link
Contributor

Testcase 1

<!DOCTYPE html>
<div style="outline: solid; height: 100px; width: 100px">
  <div style="overflow: hidden"></div>
  <div style="height: stretch; margin: 10px; border: solid cyan"></div>
  <div style="overflow: hidden"></div>
</div>
Assuming no sibling Assuming siblings don't collapse through

Testcase 2

<!DOCTYPE html>
<div style="outline: solid; height: 100px; width: 100px">
  <div></div>
  <div style="height: stretch; margin: 10px; border: solid cyan"></div>
  <div></div>
</div>
Assuming no sibling Assuming siblings don't collapse through

@davidsgrogan
Copy link
Member

Thanks!

So it appears that Blink currently behaves as if siblings don't collapse through, and Webkit behaves as if there is no sibling.

@Loirooriol
Copy link
Contributor

Well, Blink behaves as if the element had siblings that don't collapse through, even if it doesn't actually have siblings.

So I want Blink's behavior when there are preceding and following siblings, WebKit's behavior when there aren't siblings, and a mix when there are only preceding or following (but not both) siblings.

aarongable pushed a commit to chromium/chromium that referenced this issue Nov 14, 2024
1. A comment about the property -webkit-margin-collapse that we no
   longer obey.

2. A redundant conditional check.

Just some things I found while working on
w3c/csswg-drafts#11044 for stretch.

Change-Id: I9e86a436248e87192afad683b0606eb59b900698
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6022741
Reviewed-by: Morten Stenshorne <mstensho@chromium.org>
Auto-Submit: David Grogan <dgrogan@chromium.org>
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1382852}
@tabatkins
Copy link
Member

Based on some private discussion with @davidsgrogan, a few clarifications that I think need to make it into the spec:

  • "adjoining as per normal" includes when it has following siblings but they're capable of being "collapsed thru". This is the cases @Loirooriol is talking about in their earlier comment.

    I think we can safely define that away - what we want "adjoining" to mean here is "has no preceding/following in-flow sibling nodes, except possibly collapsed whitespace text nodes". This probably means, then, that we have to manually inline our definition of "adjoining" rather than reusing the existing one.

  • When a BFC child has a preceding float sibling, whether it contacts the top edge of its parent or not depends on its width (if it's narrow enough to fit next to the float). This causes similar issues as the prior. Again, I think we can just take the simple case as canon and say that preceding floats prevent it from being adjoining to the top edge, for this purpose, in all cases. (Following floats would also do so.)

The point of both of these is that our intention is just to allow an element to stretch to fill its parent in the simple, common case. We allow for reasonable complications (like the presence of abspos siblings not interfering with it), but it's fine for more complicated cases to just not work.

@tabatkins
Copy link
Member

So I think we need these edits:

diff --git a/css-sizing-4/Overview.bs b/css-sizing-4/Overview.bs
index be943838f..b994bbcbf 100644
--- a/css-sizing-4/Overview.bs
+++ b/css-sizing-4/Overview.bs
@@ -836,32 +836,52 @@ Stretch-fit Sizing: filling the containing block</h3>
 	to make its outer size as close to filling the [=containing block=] as possible
 	while still respecting the constraints imposed by min-height/min-width/max-height/max-width.
 
-	Formally, its behavior is the same as specifying an [=automatic size=]
+	In [=formatting contexts=] and axises 
+	where the relevant [=self-alignment property=] applies,
+	it gives the element the same size
+	as specifying an [=automatic size=]
 	together with a [=self-alignment property=] value of ''width/stretch''
-	(in the relevant axis),
-	except that the resulting box,
-	which can end up not exactly fitting its [=alignment container=],
-	can be subsequently aligned by its actual [=self-alignment property=] value.
+	(in the relevant axis).
+	<span class=note>(The element can then be aligned as normal
+	by its actual [=self-alignment property=] value
+	if it ends up still not exactly fitting its [=alignment container=].)</span>
 
-	Additionally,
-	in [=formatting contexts=] and axes in which the relevant [=self-alignment property=] does not apply
+	In [=formatting contexts=] and axises 
+	where the relevant [=self-alignment property=] <em>does not</em> apply
 	(such as the block axis in Block Layout, or the main axis in Flex Layout),
-	in cases where a percentage size in that axis would resolve to a definite value,
+	but a percentage size in that axis would resolve to a definite value,
 	a [=stretch-fit size=]
 	causes the box to attempt to fill its containing block--
 	behaving as ''100%''
 	but applying the resulting size to its margin box
 	instead of the box indicated by 'box-sizing'.
 	For this purpose, ''margin/auto'' margins are treated as zero,
-	and furthermore, for [=block-level boxes=] in particular,
-	if its block-start/block-end [=margin=]
-	would be adjoining to its parent's block-start/block-end [=margin=]
-	if its parent’s [=sizing properties=] all had their [=initial values=],
-	then its block-start/block-end [=margin=] is treated as zero.
+	and if either of its margins in that axis are 
+	[=adjoining its parent for stretch-fit purposes=],
+	then that margin is treated as zero.
+	<span class=note>(This causes it to size
+	as if its margin had collapsed with is parent's margin,
+	tho it does not actually change margin-collapsing behavior.)</span>
 
-	Note: Consequently, if neither ''align-self/stretch'' alignment applies
-	nor percentage sizing can resolve,
-	then the box will resolve to its [=automatic size=].
+	<div algorithm>
+		A box's margin is 
+		<dfn export>adjoining its parent for stretch-fit purposes</dfn>
+		if all of the following are true:
+
+		* it is a [=block-level box=]
+		* the margin would be [=adjoining=] its parent's matching margin,
+			assuming the parent's [=sizing properties=] all had their [=initial values=]
+		* the box does not have any preceding/following (as appropriate)
+			[=in-flow=] sibling elements or [=text runs=],
+			except [=collapsed white space=]
+		* if the box is a [=block formatting context=],
+			the box does not have any preceding/following (as appropriate) [=floating=] sibling elements
+	</div>
+
+	In all other cases
+	(when neither ''align-self/stretch'' alignment applies
+	nor percentage sizing can resolve),
+	the box resolves to its [=automatic size=].
 
 	<div class="example">
 		For example, given the following HTML representing two [=block boxes=]:

@fantasai, does this look reasonable?

@tabatkins
Copy link
Member

We could also go the other way with preceding floats, and say they don't affect adjoining-ness. Depends on which case we think will be more common and thus annoying to get wrong.

@davidsgrogan
Copy link
Member

So I think we need these edits:

diff --git a/css-sizing-4/Overview.bs b/css-sizing-4/Overview.bs
index be943838f..b994bbcbf 100644
--- a/css-sizing-4/Overview.bs
+++ b/css-sizing-4/Overview.bs
 [clip]
+	<div algorithm>
+		A box's margin is 
+		<dfn export>adjoining its parent for stretch-fit purposes</dfn>
+		if all of the following are true:
+
+		* it is a [=block-level box=]
+		* the margin would be [=adjoining=] its parent's matching margin,
+			assuming the parent's [=sizing properties=] all had their [=initial values=]
+		* the box does not have any preceding/following (as appropriate)
+			[=in-flow=] sibling elements or [=text runs=],
+			except [=collapsed white space=]
+		* if the box is a [=block formatting context=],
+			the box does not have any preceding/following (as appropriate) [=floating=] sibling elements
+	</div>

We obviously don't want to restrict that last bullet point to block formatting contexts (right?). Should it link to [=independent-formatting-context=] instead of [=block-formatting-context=]?

@astearns astearns moved this from FTF agenda items to Regular agenda items in CSSWG January 2025 meeting Jan 22, 2025
@astearns astearns moved this from Regular agenda items to Friday morning in CSSWG January 2025 meeting Jan 28, 2025
@fantasai
Copy link
Collaborator

I believe #11044 (comment) preserves the intent of the spec, so +1 from me.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-sizing-4] How does height: stretch interact with margin collapsing with parent, and agreed to the following:

  • RESOLVED: Accept proposal
The full IRC log of that discussion <fantasai> TabAtkins: The spec for height:stretch around for awhile. While trying to implement, we ran into some issues with its definition
<fantasai> TabAtkins: mainly what info it's trying to rely on and when that info would be available
<fantasai> TabAtkins: also consistency issues
<fantasai> TabAtkins: big problem is that the rules as stated can result in multiple children getting different sizes based on where they are in the element
<fantasai> TabAtkins: or a single element changing size depending on presence of other elements
<fantasai> TabAtkins: means that mutating DOM can change expectations for what height should be
<fantasai> TabAtkins: after working through implications, settled on proposal that addresses the core use cases but simplifies inputs to stable
<fantasai> TabAtkins: height:stretch always fills parent's content box, taking into account child's own mbp
<fantasai> TabAtkins: if parent settings would prevent collapsing, we assume no collapsing; otherwise assume collapsing
<fantasai> TabAtkins: same thing for bottom margin
<fantasai> TabAtkins: in most cases this will do what you want
<fantasai> TabAtkins: if parent has border, child will fit exactly inside considering its own margins
<fantasai> TabAtkins: if no border, chid will fit exactly inside ignoring its own margins
<fantasai> TabAtkins: If you're doing this for multiple elements, all stretched elements will be the same size
<fantasai> TabAtkins: There are a few cases where this will cause item to be a little too large
<fantasai> TabAtkins: e.g. assumptions about collapsing were wrong
<fantasai> TabAtkins: e.g. sibling prevents collapsing
<fantasai> TabAtkins: but at that point you're violating the base contract of this feature, which is that you're the only thing in the parent
<fantasai> TabAtkins: other cases you get the sizing you expect
<TabAtkins> fantasai: the intention we were going with is tha tyou just pretend the item is the only thing in the box and do something simple about margin collapse
<TabAtkins> fantasai: in particular, a fixed height on the parent would normally prevent margin collapse but would truncate the margin; we didn't want that to cause non-collapse behavior for calculating the child's size
<TabAtkins> fantasai: i think Tab's proposal is basically a more correct version of what the spec is tryign to do
<fantasai> astearns: No compat concerns?
<fantasai> TabAtkins: no public implementations yet
<fantasai> iank_: for stretch keyword, no one has shipped yet
<fantasai> iank_: Blink will ship this with stretch, and then try to make -webkit-fill-available match it as a separate step
<fantasai> iank_: I don't think we'll run into issues due to current non-interop
<fantasai> astearns: proposed to adopt Tab's proposal
<fantasai> RESOLVED: Accept proposal

@tabatkins
Copy link
Member

tabatkins commented Feb 20, 2025

All right, edits committed. I'd appreciate another eye on this to make sure I'm doing the right thing.

/cc @fantasai @davidsgrogan @bfgeek

@Loirooriol
Copy link
Contributor

Behaves as the property's [=initial value=].

That's not what was resolved in #11006 (comment). Blink treats it as 0px in min properties, not as auto:

<!DOCTYPE html>
<style>
.stretch { min-height: -moz-available; min-height: -webkit-fill-available; min-height: stretch }
.item { width: 50px; border: solid }
.item::after { content: ""; display: block; height: 75px }
</style>
<div style="display: inline-block">
  <div class="item" style="aspect-ratio: 1"></div>
</div>
<div style="display: inline-block">
  <div class="item stretch" style="aspect-ratio: 1"></div>
</div>
<div style="display: inline-flex; flex-direction: column">
  <div class="item" style="flex-basis: 50px"></div>
</div>
<div style="display: inline-flex; flex-direction: column">
  <div class="item stretch" style="flex-basis: 50px"></div>
</div>
<div style="display: inline-grid; grid-template-rows: auto; height: 50px">
  <div class="item"></div>
</div>
<div style="display: inline-grid; grid-template-rows: auto; height: 50px">
  <div class="item stretch"></div>
</div>

@tabatkins
Copy link
Member

Sigh, yeah, that was me forgetting, once again, that auto is the initial value rather than 0. I'll fix, thanks.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Mar 5, 2025
Normally stretched elements shrink to leave room for their margins. But
in the case of collapsing margins, not always. If the parent block has
no border, no margin, and is not a new BFC, don't leave room for the
margin on that edge.

Described in more detail at
w3c/csswg-drafts#11044 (comment)

This behavior is still behind a flag.

Change-Id: I3397cd051e777f9c0a346094fa23c5b042d82c2c
Bug: 41253915
aarongable pushed a commit to chromium/chromium that referenced this issue Mar 5, 2025
Normally stretched elements shrink to leave room for their margins. But
in the case of collapsing margins, not always. If the parent block has
no border, no margin, and is not a new BFC, don't leave room for the
margin on that edge.

Described in more detail at
w3c/csswg-drafts#11044 (comment)

This behavior is still behind a flag.

Change-Id: I3397cd051e777f9c0a346094fa23c5b042d82c2c
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6180930
Commit-Queue: David Grogan <dgrogan@chromium.org>
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1428087}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Mar 5, 2025
Normally stretched elements shrink to leave room for their margins. But
in the case of collapsing margins, not always. If the parent block has
no border, no margin, and is not a new BFC, don't leave room for the
margin on that edge.

Described in more detail at
w3c/csswg-drafts#11044 (comment)

This behavior is still behind a flag.

Change-Id: I3397cd051e777f9c0a346094fa23c5b042d82c2c
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6180930
Commit-Queue: David Grogan <dgrogan@chromium.org>
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1428087}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Mar 5, 2025
Normally stretched elements shrink to leave room for their margins. But
in the case of collapsing margins, not always. If the parent block has
no border, no margin, and is not a new BFC, don't leave room for the
margin on that edge.

Described in more detail at
w3c/csswg-drafts#11044 (comment)

This behavior is still behind a flag.

Change-Id: I3397cd051e777f9c0a346094fa23c5b042d82c2c
Bug: 41253915
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6180930
Commit-Queue: David Grogan <dgrogan@chromium.org>
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1428087}
Loirooriol added a commit to Loirooriol/servo that referenced this issue Mar 11, 2025
The CSSWG resolved that `block-size: stretch` on a block-level box
stretches the margin box to fill the parent. However, if the parent
doesn't have padding nor border, and doesn't establish an independent
formatting context, then we assume that the margins will collapse.
Therefore, we treat the margins as zero when resolving the stretch size,
regardless of whether they will actually end up collapsing.

w3c/csswg-drafts#11044 (comment)
https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
@Loirooriol
Copy link
Contributor

The spec needs to consider floats, filed #11905

Loirooriol added a commit to Loirooriol/servo that referenced this issue Mar 11, 2025
The CSSWG resolved that `block-size: stretch` on a block-level box
stretches the margin box to fill the parent. However, if the parent
doesn't have padding nor border, and doesn't establish an independent
formatting context, then we assume that the margins will collapse.
Therefore, we treat the margins as zero when resolving the stretch size,
regardless of whether they will actually end up collapsing.

w3c/csswg-drafts#11044 (comment)
https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Loirooriol added a commit to Loirooriol/servo that referenced this issue Mar 11, 2025
The CSSWG resolved that `block-size: stretch` on a block-level box
stretches the margin box to fill the parent. However, if the parent
doesn't have padding nor border, and doesn't establish an independent
formatting context, then we assume that the margins will collapse.
Therefore, we treat the margins as zero when resolving the stretch size,
regardless of whether they will actually end up collapsing.

w3c/csswg-drafts#11044 (comment)
https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Loirooriol added a commit to Loirooriol/servo that referenced this issue Mar 11, 2025
The CSSWG resolved that `block-size: stretch` on a block-level box
stretches the margin box to fill the parent. However, if the parent
doesn't have padding nor border, and doesn't establish an independent
formatting context, then we assume that the margins will collapse.
Therefore, we treat the margins as zero when resolving the stretch size,
regardless of whether they will actually end up collapsing.

w3c/csswg-drafts#11044 (comment)
https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
github-merge-queue bot pushed a commit to servo/servo that referenced this issue Mar 11, 2025
…es (#35904)

The CSSWG resolved that `block-size: stretch` on a block-level box
stretches the margin box to fill the parent. However, if the parent
doesn't have padding nor border, and doesn't establish an independent
formatting context, then we assume that the margins will collapse.
Therefore, we treat the margins as zero when resolving the stretch size,
regardless of whether they will actually end up collapsing.

w3c/csswg-drafts#11044 (comment)
https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Mar 11, 2025
…llapsing interactions, a=testonly

Automatic update from web-platform-tests
[layout] Implement stretch and margin collapsing interactions

Normally stretched elements shrink to leave room for their margins. But
in the case of collapsing margins, not always. If the parent block has
no border, no margin, and is not a new BFC, don't leave room for the
margin on that edge.

Described in more detail at
w3c/csswg-drafts#11044 (comment)

This behavior is still behind a flag.

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

--

wpt-commits: a220728d2ef826fb20651217b1f167590285c2ff
wpt-pr: 51117
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Friday morning
Development

No branches or pull requests

9 participants