Repository navigation
[css-sizing-4] How does height: stretch interact with margin collapsing with parent #11044
Description
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
stretchbehave "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 hasstretch.) - The current spec definition of margin-collapsing is intentionally asymmetric: blocks with a non-
autoheight 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
stretchsizes 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?
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsFriday morning
Activity
Loirooriol commentedon Oct 17, 2024
Quick test: https://software.hixie.ch/utilities/js/live-dom-viewer/saved/13208
I think the spec says that magenta should be like WebKit, and cyan like Blink, which is what looks the best to me.
dbaron commentedon 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 commentedon Oct 17, 2024
Yes, the top margin collapses as normal, the bottom one doesn't (because of
height: 100px) but it looks like collapsing.Loirooriol commentedon Oct 17, 2024
Maybe it's clearer like
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.[layout] Accept 'stretch' keyword as a width/height
[layout] Accept 'stretch' keyword as a width/height
dbaron commentedon 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 commentedon Oct 17, 2024
I think it's the latter, the former seems weird.
[layout] Accept 'stretch' keyword as a width/height
bfgeek commentedon Oct 17, 2024
Some practical constraints from an engine perspective.
Blink doesn't know anything about any proceeding margins, e.g.
(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.
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
stretchas a pure alias of-webkit-fill-available.Ian
Loirooriol commentedon Oct 18, 2024
Blink and WebKit have different behaviors, so it's probably fine if we choose one or the other depending on the case.
In Servo we parallelize block layout (when there are no floats), so we also have this problem for preceding margins.
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.
I think that ignoring margins for non-BFC parent is too restrictive.
So I have another proposal. Given that:
stretchdoesn't make that much sense if there are siblingsThen we could, for the purpose of resolving a vertical
stretchon a block-level box: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:
Seems fine from an implementation POV.
Bug 1925382 [wpt PR 48680] - [layout] Accept 'stretch' keyword as a w…
Bug 1925382 [wpt PR 48680] - [layout] Accept 'stretch' keyword as a w…
Bug 1925382 [wpt PR 48680] - [layout] Accept 'stretch' keyword as a w…
56 remaining items
[layout] Implement stretch and margin collapsing interactions
[layout] Implement stretch and margin collapsing interactions
[layout] Implement stretch and margin collapsing interactions
[layout] Implement stretch and margin collapsing interactions
layout: Fix interaction of margin and stretch size on block-level boxes
Loirooriol commentedon Mar 11, 2025
The spec needs to consider floats, filed #11905
layout: Fix interaction of margin and stretch size on block-level boxes
layout: Fix interaction of margin and stretch size on block-level boxes
layout: Fix interaction of margin and stretch size on block-level boxes
layout: Fix interaction of margin and stretch size on block-level box…
Bug 1951830 [wpt PR 51117] - [layout] Implement stretch and margin co…
Bug 1951830 [wpt PR 51117] - [layout] Implement stretch and margin co…
Bug 1925382 [wpt PR 48680] - [layout] Accept 'stretch' keyword as a w…
Bug 1951830 [wpt PR 51117] - [layout] Implement stretch and margin co…