layout: Allow collapsing bottom margins with any indefinite block size (#36278)

According to CSS2, the bottom margin of a block container can collapse
with the bottom margin of its last in-flow child if `height` computes to
`auto`.

However, according to CSS Sizing, that was "legacy spec prose" and
should be interpreted as "behaves as `auto`".

Therefore, cyclic percentages and intrinsic keywords like `min-content`
shouldn't prevent margin collapse, because they behave as `auto`.

This change aligns Servo with Gecko and Blink, but diverges from WebKit.

https://www.w3.org/TR/CSS22/box.html#collapsing-margins
https://www.w3.org/TR/css-sizing/#behave-auto

Testing:
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-001.html`
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-002.html`
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-003.html`
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-004.html`
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-005.html`

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Oriol Brufau 2025-04-02 05:10:04 -07:00 committed by GitHub
parent 3bc0eeab8f
commit 1f13e8b596
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 181 additions and 1 deletions

View file

@ -1012,7 +1012,7 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
let end_margin_can_collapse_with_children = collapsed_through ||
(pbm.padding.block_end == Au::zero() &&
pbm.border.block_end == Au::zero() &&
computed_block_size.is_auto());
!containing_block_for_children.size.block.is_definite());
if end_margin_can_collapse_with_children {
block_margins_collapsed_with_children
.end

View file

@ -248765,6 +248765,71 @@
{}
]
],
"margin-collapse-with-indefinite-block-size-001.html": [
"47d2a0a043d32ba6220c1dd6a26859908a19bf6e",
[
null,
[
[
"/css/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
"margin-collapse-with-indefinite-block-size-002.html": [
"eb401c92b5e9475129f39be9980f47f42cb2bfa0",
[
null,
[
[
"/css/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
"margin-collapse-with-indefinite-block-size-003.html": [
"51f16f68e6998de4956a5f0615b49406fcacb02e",
[
null,
[
[
"/css/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
"margin-collapse-with-indefinite-block-size-004.html": [
"c393560d6c6ce799943db09468ba8e5cb0e90a5c",
[
null,
[
[
"/css/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
"margin-collapse-with-indefinite-block-size-005.html": [
"27814994aaac7ead76f67d051e8744323e8f4247",
[
null,
[
[
"/css/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
"max-content-input-001.html": [
"aabbea015748f9276718e2ba9728efc375c8910b",
[

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css2/#collapsing-margins">
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#behave-auto">
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#cyclic-percentage-contribution">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="assert" content="
According to CSS2, the bottom margin of a block container can collapse
with the bottom margin of its last in-flow child if `height` computes
to `auto`.
However, according to CSS Sizing, that was 'legacy spec prose' and
should be interpreted as 'behaves as `auto`'.
Therefore, a cyclic percentage in the preferred block size property
shouldn't prevent margin collapse, because it behaves as `auto`.
">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div style="width: 100px; height: 100%; background: red">
<div style="height: 100px; margin-bottom: 100px; background: green"></div>
</div>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css2/#collapsing-margins">
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#behave-auto">
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#valdef-width-min-content">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="assert" content="
According to CSS2, the bottom margin of a block container can collapse
with the bottom margin of its last in-flow child if `height` computes
to `auto`.
However, according to CSS Sizing, that was 'legacy spec prose' and
should be interpreted as 'behaves as `auto`'.
Therefore, a `min-content` value in the preferred block size property
shouldn't prevent margin collapse, because it behaves as `auto`.
">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div style="width: 100px; height: min-content; background: red">
<div style="height: 100px; margin-bottom: 100px; background: green"></div>
</div>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css2/#collapsing-margins">
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#behave-auto">
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#valdef-width-max-content">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="assert" content="
According to CSS2, the bottom margin of a block container can collapse
with the bottom margin of its last in-flow child if `height` computes
to `auto`.
However, according to CSS Sizing, that was 'legacy spec prose' and
should be interpreted as 'behaves as `auto`'.
Therefore, a `max-content` value in the preferred block size property
shouldn't prevent margin collapse, because it behaves as `auto`.
">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div style="width: 100px; height: max-content; background: red">
<div style="height: 100px; margin-bottom: 100px; background: green"></div>
</div>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css2/#collapsing-margins">
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#behave-auto">
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#valdef-width-fit-content">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="assert" content="
According to CSS2, the bottom margin of a block container can collapse
with the bottom margin of its last in-flow child if `height` computes
to `auto`.
However, according to CSS Sizing, that was 'legacy spec prose' and
should be interpreted as 'behaves as `auto`'.
Therefore, a `fit-content` value in the preferred block size property
shouldn't prevent margin collapse, because it behaves as `auto`.
">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div style="width: 100px; height: fit-content; background: red">
<div style="height: 100px; margin-bottom: 100px; background: green"></div>
</div>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css2/#collapsing-margins">
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#behave-auto">
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="assert" content="
According to CSS2, the bottom margin of a block container can collapse
with the bottom margin of its last in-flow child if `height` computes
to `auto`.
However, according to CSS Sizing, that was 'legacy spec prose' and
should be interpreted as 'behaves as `auto`'.
Therefore, an indefinite `stretch` in the preferred block size property
shouldn't prevent margin collapse, because it behaves as `auto`.
">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div style="width: 100px; height: stretch; background: red">
<div style="height: 100px; margin-bottom: 100px; background: green"></div>
</div>