Skip to content

Commit 8e5ca18

Browse files
[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}
1 parent 9d172e9 commit 8e5ca18

9 files changed

+822
-64
lines changed

css/css-sizing/stretch/block-height-002.tentative.html css/css-sizing/stretch/block-height-002.html

+3-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@
1212
font: 20px/1 Ahem;
1313
}
1414
</style>
15-
<p>This test asserts the behavior seemingly agreed upon through
16-
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This
17-
is unlikely to be the final specified behavior, hence the test is marked
18-
tentative.</p>
15+
<p>These tests assert the behavior described at
16+
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601
17+
</p>
1918

2019
<main>
2120
<!-- Example 9

css/css-sizing/stretch/block-height-003.tentative.html css/css-sizing/stretch/block-height-003.html

+3-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
</style>
1515

1616
<!--
17-
<p>This test asserts the behavior seemingly agreed upon through
18-
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This
19-
is unlikely to be the final specified behavior, hence the test is marked
20-
tentative.</p>
17+
<p>These tests assert the behavior described at
18+
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601
19+
</p>
2120
-->
2221

2322
<div class="surrounding-block"></div>

css/css-sizing/stretch/block-height-004.tentative.html css/css-sizing/stretch/block-height-004.html

+26-31
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<script src='/resources/testharnessreport.js'></script>
77
<script src="/resources/check-layout-th.js"></script>
88
<meta name="assert"
9-
content="demonstrate the behavior described in https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2422165458">
9+
content="margins of the stretched element are accounted for correctly in a variety of scenarios, mostly around siblings">
1010

1111
<style>
1212
.outer {
@@ -20,17 +20,11 @@
2020
height: stretch;
2121
margin: 10px;
2222
}
23-
24-
p {
25-
margin-top: 20px;
26-
margin-bottom: 0px;
27-
}
2823
</style>
2924

30-
<p>This test asserts the behavior seemingly agreed upon through
31-
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This
32-
is unlikely to be the final specified behavior, hence the test is marked
33-
tentative.</p>
25+
<h2>These tests assert the behavior described at
26+
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601
27+
</h2>
3428

3529
<p>Basic case: treat margins as 0.</p>
3630
<div class="outer">
@@ -40,54 +34,55 @@
4034
</div>
4135

4236
<p>
43-
When resolving stretch, don't treat margins as 0 if there is a sibling on that
44-
side. (Hand-wavy: we don't collapse margins through siblings for the purpose
45-
of resolving stretched heights.)</p>
46-
<p>
47-
Then when actually doing margin collapsing, .inner's margins DON'T collapse
48-
with .outer's because of the usual rule that margins don't collapse through
49-
new formatting contexts.
37+
When resolving stretch treat both block margins as 0 because the parent is
38+
not a BFC and has no top or bottom content edge (i.e. border + padding = 0).
39+
<br>But cyan's margins will not actually collapse through its IFC-siblings so
40+
there is overflow:
5041
</p>
5142
<div class="outer">
5243
<div style="overflow: hidden"></div>
53-
<div class="inner" style="border: solid cyan;" data-expected-height="80"
44+
<div class="inner" style="border: solid cyan;" data-expected-height="100"
5445
data-offset-y="10">
5546
</div>
5647
<div style="overflow: hidden"></div>
5748
</div>
5849

59-
<p>When resolving stretch, don't treat margins as 0 if there is a sibling on
60-
that side. (Hand-wavy: we don't collapse margins through siblings for the
61-
purpose of resolving stretched heights.)</p>
62-
<p>
63-
Then when actually doing margin collapsing, .inner's margins DO collapse with
64-
.outer's because they collapse through the empty siblings.
65-
</p>
6650
<div class="outer">
6751
<div></div>
68-
<div class="inner" style="border: solid blue;" data-expected-height="80"
52+
<div class="inner" style="border: solid blue;" data-expected-height="100"
6953
data-offset-y="0">
7054
</div>
7155
<div></div>
7256
</div>
7357

74-
<p>Only treat the BOTTOM margin as 0. Margins do collapse, so top edges touch.
75-
</p>
7658
<div class="outer">
7759
<div></div>
78-
<div class="inner" style="border: solid purple;" data-expected-height="90"
60+
<div class="inner" style="border: solid purple;" data-expected-height="100"
7961
data-offset-y="0">
8062
</div>
8163
</div>
8264

83-
<p>Only treat the TOP margin as 0. Margins do collapse, so top edges touch.</p>
8465
<div class="outer">
85-
<div class="inner" style="border: solid lime;" data-expected-height="90"
66+
<div class="inner" style="border: solid lime;" data-expected-height="100"
8667
data-offset-y="0">
8768
</div>
8869
<div></div>
8970
</div>
9071

72+
<p>Parent has non-zero bottom border, so only top margin is treated as 0:</p>
73+
<div class="outer" style="border-bottom: 5px dashed blue;">
74+
<div class="inner" style="border: solid brown;" data-expected-height="90"
75+
data-offset-y="0">
76+
</div>
77+
</div>
78+
79+
<p>Parent has non-zero top padding so only bottom margin is treated as 0:</p>
80+
<div class="outer" style="padding-top: 5px;">
81+
<div class="inner" style="border: solid darkgreen;" data-expected-height="90"
82+
data-offset-y="15"> <!-- 15 = 10px top margin + parent's padding-->
83+
</div>
84+
</div>
85+
9186
<p>Account for the margins when parent establishes a BFC.</p>
9287
<div class="outer" style="display: flow-root;">
9388
<div class="inner" style="border: solid orange;" data-expected-height="80"

css/css-sizing/stretch/block-height-005.tentative.html css/css-sizing/stretch/block-height-005.html

+4-18
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<script src='/resources/testharnessreport.js'></script>
77
<script src="/resources/check-layout-th.js"></script>
88
<meta name="assert"
9-
content="preceding floats don't prevent margin adjoiningness for stretch sizing purposes">
9+
content="stretch sizing treating margins as 0 isn't affected by preceding floats">
1010

1111
<style>
1212
.outer {
@@ -22,20 +22,12 @@
2222
height: 30px;
2323
background: skyblue;
2424
}
25-
26-
p {
27-
margin-top: 20px;
28-
margin-bottom: 0px;
29-
}
3025
</style>
3126

32-
<p>This test asserts the behavior seemingly agreed upon through
33-
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This
34-
is unlikely to be the final specified behavior, hence the test is marked
35-
tentative.</p>
27+
<p>These tests assert the behavior described at
28+
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601
29+
</p>
3630

37-
<p>New BFC fits next to float, so top margins will collapse, so we want the
38-
stretched height to match .outer's height.</p>
3931
<div class="outer">
4032
<div class="float"></div>
4133
<div
@@ -44,8 +36,6 @@
4436
</div>
4537
</div>
4638

47-
<p>New BFC does not fit next to float, so margins DON'T collapse, but for
48-
simplicity we still ignore margins when stretch sizing</p>
4939
<div class="outer">
5040
<div class="float"></div>
5141
<div
@@ -54,8 +44,6 @@
5444
</div>
5545
</div>
5646

57-
<p>In-flow child overlaps the float, so margins DO collapse, so we want the
58-
stretched height to match .outer's height.</p>
5947
<div class="outer">
6048
<div class="float"></div>
6149
<div
@@ -64,8 +52,6 @@
6452
</div>
6553
</div>
6654

67-
<p>In-flow child clears the float, so margins DON'T collapse, but for
68-
simplicity we still ignore margins when stretch sizing</p>
6955
<div class="outer">
7056
<div class="float"></div>
7157
<div

css/css-sizing/stretch/block-height-006.tentative.html css/css-sizing/stretch/block-height-006.html

-7
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,6 @@
1616
}
1717
</style>
1818

19-
<!--
20-
<p>This test asserts the behavior seemingly agreed upon through
21-
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This
22-
is unlikely to be the final specified behavior, hence the test is marked
23-
tentative.</p>
24-
-->
25-
2619
<p>Test passes if there is a filled green square and <strong>no red</strong>.
2720
</p>
2821
<div id="reference-overlapped-red"></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<!DOCTYPE html>
2+
<link rel="help"
3+
href="https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing">
4+
<meta name="assert"
5+
content="margins of the stretched element are accounted for correctly in various writing mode combinations and presence of borders">
6+
<script src="/resources/testharness.js"></script>
7+
<script src="/resources/testharnessreport.js"></script>
8+
<script src="/resources/check-layout-th.js"></script>
9+
10+
<style>
11+
.container {
12+
width: 50px;
13+
height: 50px;
14+
margin: 3px;
15+
background: magenta;
16+
position: relative;
17+
}
18+
19+
.child {
20+
margin: 1px 3px 5px 7px;
21+
background: cyan;
22+
font-size: 10px;
23+
}
24+
</style>
25+
26+
<div id="log"></div>
27+
<div class="container" style="border-top: 5px solid;">
28+
<div class="child" data-expected-width="20" data-expected-height="49"
29+
data-offset-y="1" style="width: 20px; height: stretch;">1</div>
30+
</div>
31+
<div class="container" style="border-top: 5px solid;">
32+
<div class="child" data-expected-width="40" data-expected-height="20"
33+
data-offset-y="1" style="width: stretch; height: 20px;">2</div>
34+
</div>
35+
<div class="container" style="border-right: 5px solid;">
36+
<div class="child" data-expected-width="20" data-expected-height="50"
37+
data-offset-y="0" style="width: 20px; height: stretch;">3</div>
38+
</div>
39+
<div class="container" style="border-right: 5px solid;">
40+
<div class="child" data-expected-width="40" data-expected-height="20"
41+
data-offset-y="0" style="width: stretch; height: 20px;">4</div>
42+
</div>
43+
<div class="container" style="border-top: 5px solid;">
44+
<div class="child" data-expected-width="20" data-expected-height="49"
45+
data-offset-y="1"
46+
style="writing-mode: vertical-rl; width: 20px; height: stretch;">5</div>
47+
</div>
48+
<div class="container" style="border-top: 5px solid;">
49+
<div class="child" data-expected-width="40" data-expected-height="20"
50+
data-offset-y="1"
51+
style="writing-mode: vertical-rl; width: stretch; height: 20px;">6</div>
52+
</div>
53+
<div class="container" style="border-right: 5px solid;">
54+
<div class="child" data-expected-width="20" data-expected-height="50"
55+
data-offset-y="0"
56+
style="writing-mode: vertical-rl; width: 20px; height: stretch;">7</div>
57+
</div>
58+
<div class="container" style="border-right: 5px solid;">
59+
<div class="child" data-expected-width="40" data-expected-height="20"
60+
data-offset-y="0"
61+
style="writing-mode: vertical-rl; width: stretch; height: 20px;">8</div>
62+
</div>
63+
<div class="container" style="border-top: 5px solid;">
64+
<div class="child" data-expected-width="20" data-expected-height="49"
65+
data-offset-y="1"
66+
style="writing-mode: vertical-lr; width: 20px; height: stretch;">9</div>
67+
</div>
68+
<div class="container" style="border-top: 5px solid;">
69+
<div class="child" data-expected-width="40" data-expected-height="20"
70+
data-offset-y="1"
71+
style="writing-mode: vertical-lr; width: stretch; height: 20px;">10</div>
72+
</div>
73+
<div class="container" style="border-right: 5px solid;">
74+
<div class="child" data-expected-width="20" data-expected-height="50"
75+
data-offset-y="0"
76+
style="writing-mode: vertical-lr; width: 20px; height: stretch;">11</div>
77+
</div>
78+
<div class="container" style="border-right: 5px solid;">
79+
<div class="child" data-expected-width="40" data-expected-height="20"
80+
data-offset-y="0"
81+
style="writing-mode: vertical-lr; width: stretch; height: 20px;">12</div>
82+
</div>
83+
<div class="container" style="border-top: 5px solid;">
84+
<div class="child" data-expected-width="20" data-expected-height="49"
85+
data-offset-y="1"
86+
style="writing-mode: sideways-rl; width: 20px; height: stretch;">13</div>
87+
</div>
88+
<div class="container" style="border-top: 5px solid;">
89+
<div class="child" data-expected-width="40" data-expected-height="20"
90+
data-offset-y="1"
91+
style="writing-mode: sideways-rl; width: stretch; height: 20px;">14</div>
92+
</div>
93+
<div class="container" style="border-right: 5px solid;">
94+
<div class="child" data-expected-width="20" data-expected-height="50"
95+
data-offset-y="0"
96+
style="writing-mode: sideways-rl; width: 20px; height: stretch;">15</div>
97+
</div>
98+
<div class="container" style="border-right: 5px solid;">
99+
<div class="child" data-expected-width="40" data-expected-height="20"
100+
data-offset-y="0"
101+
style="writing-mode: sideways-rl; width: stretch; height: 20px;">16</div>
102+
</div>
103+
<div class="container" style="border-top: 5px solid;">
104+
<div class="child" data-expected-width="20" data-expected-height="49"
105+
data-offset-y="1"
106+
style="writing-mode: sideways-lr; width: 20px; height: stretch;">17</div>
107+
</div>
108+
<div class="container" style="border-top: 5px solid;">
109+
<div class="child" data-expected-width="40" data-expected-height="20"
110+
data-offset-y="1"
111+
style="writing-mode: sideways-lr; width: stretch; height: 20px;">18</div>
112+
</div>
113+
<div class="container" style="border-right: 5px solid;">
114+
<div class="child" data-expected-width="20" data-expected-height="50"
115+
data-offset-y="0"
116+
style="writing-mode: sideways-lr; width: 20px; height: stretch;">19</div>
117+
</div>
118+
<div class="container" style="border-right: 5px solid;">
119+
<div class="child" data-expected-width="40" data-expected-height="20"
120+
data-offset-y="0"
121+
style="writing-mode: sideways-lr; width: stretch; height: 20px;">20</div>
122+
</div>
123+
124+
<script>
125+
checkLayout('.child');
126+
</script>

0 commit comments

Comments
 (0)