Skip to content

Commit

Permalink
[layout] Implement stretch and margin collapsing interactions
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Ian Kilpatrick <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1428087}
  • Loading branch information
davidsgrogan authored and chromium-wpt-export-bot committed Mar 5, 2025
1 parent 9d172e9 commit a220728
Show file tree
Hide file tree
Showing 9 changed files with 822 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
font: 20px/1 Ahem;
}
</style>
<p>This test asserts the behavior seemingly agreed upon through
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This
is unlikely to be the final specified behavior, hence the test is marked
tentative.</p>
<p>These tests assert the behavior described at
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601
</p>

<main>
<!-- Example 9
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
</style>

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

<div class="surrounding-block"></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<script src='/resources/testharnessreport.js'></script>
<script src="/resources/check-layout-th.js"></script>
<meta name="assert"
content="demonstrate the behavior described in https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2422165458">
content="margins of the stretched element are accounted for correctly in a variety of scenarios, mostly around siblings">

<style>
.outer {
Expand All @@ -20,17 +20,11 @@
height: stretch;
margin: 10px;
}

p {
margin-top: 20px;
margin-bottom: 0px;
}
</style>

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

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

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

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

<p>Only treat the BOTTOM margin as 0. Margins do collapse, so top edges touch.
</p>
<div class="outer">
<div></div>
<div class="inner" style="border: solid purple;" data-expected-height="90"
<div class="inner" style="border: solid purple;" data-expected-height="100"
data-offset-y="0">
</div>
</div>

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

<p>Parent has non-zero bottom border, so only top margin is treated as 0:</p>
<div class="outer" style="border-bottom: 5px dashed blue;">
<div class="inner" style="border: solid brown;" data-expected-height="90"
data-offset-y="0">
</div>
</div>

<p>Parent has non-zero top padding so only bottom margin is treated as 0:</p>
<div class="outer" style="padding-top: 5px;">
<div class="inner" style="border: solid darkgreen;" data-expected-height="90"
data-offset-y="15"> <!-- 15 = 10px top margin + parent's padding-->
</div>
</div>

<p>Account for the margins when parent establishes a BFC.</p>
<div class="outer" style="display: flow-root;">
<div class="inner" style="border: solid orange;" data-expected-height="80"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<script src='/resources/testharnessreport.js'></script>
<script src="/resources/check-layout-th.js"></script>
<meta name="assert"
content="preceding floats don't prevent margin adjoiningness for stretch sizing purposes">
content="stretch sizing treating margins as 0 isn't affected by preceding floats">

<style>
.outer {
Expand All @@ -22,20 +22,12 @@
height: 30px;
background: skyblue;
}

p {
margin-top: 20px;
margin-bottom: 0px;
}
</style>

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

<p>New BFC fits next to float, so top margins will collapse, so we want the
stretched height to match .outer's height.</p>
<div class="outer">
<div class="float"></div>
<div
Expand All @@ -44,8 +36,6 @@
</div>
</div>

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

<p>In-flow child overlaps the float, so margins DO collapse, so we want the
stretched height to match .outer's height.</p>
<div class="outer">
<div class="float"></div>
<div
Expand All @@ -64,8 +52,6 @@
</div>
</div>

<p>In-flow child clears the float, so margins DON'T collapse, but for
simplicity we still ignore margins when stretch sizing</p>
<div class="outer">
<div class="float"></div>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@
}
</style>

<!--
<p>This test asserts the behavior seemingly agreed upon through
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2486935794. This
is unlikely to be the final specified behavior, hence the test is marked
tentative.</p>
-->

<p>Test passes if there is a filled green square and <strong>no red</strong>.
</p>
<div id="reference-overlapped-red"></div>
Expand Down
126 changes: 126 additions & 0 deletions css/css-sizing/stretch/block-height-007.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<!DOCTYPE html>
<link rel="help"
href="https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing">
<meta name="assert"
content="margins of the stretched element are accounted for correctly in various writing mode combinations and presence of borders">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/check-layout-th.js"></script>

<style>
.container {
width: 50px;
height: 50px;
margin: 3px;
background: magenta;
position: relative;
}

.child {
margin: 1px 3px 5px 7px;
background: cyan;
font-size: 10px;
}
</style>

<div id="log"></div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="49"
data-offset-y="1" style="width: 20px; height: stretch;">1</div>
</div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="1" style="width: stretch; height: 20px;">2</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="50"
data-offset-y="0" style="width: 20px; height: stretch;">3</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="0" style="width: stretch; height: 20px;">4</div>
</div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="49"
data-offset-y="1"
style="writing-mode: vertical-rl; width: 20px; height: stretch;">5</div>
</div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="1"
style="writing-mode: vertical-rl; width: stretch; height: 20px;">6</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="50"
data-offset-y="0"
style="writing-mode: vertical-rl; width: 20px; height: stretch;">7</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="0"
style="writing-mode: vertical-rl; width: stretch; height: 20px;">8</div>
</div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="49"
data-offset-y="1"
style="writing-mode: vertical-lr; width: 20px; height: stretch;">9</div>
</div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="1"
style="writing-mode: vertical-lr; width: stretch; height: 20px;">10</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="50"
data-offset-y="0"
style="writing-mode: vertical-lr; width: 20px; height: stretch;">11</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="0"
style="writing-mode: vertical-lr; width: stretch; height: 20px;">12</div>
</div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="49"
data-offset-y="1"
style="writing-mode: sideways-rl; width: 20px; height: stretch;">13</div>
</div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="1"
style="writing-mode: sideways-rl; width: stretch; height: 20px;">14</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="50"
data-offset-y="0"
style="writing-mode: sideways-rl; width: 20px; height: stretch;">15</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="0"
style="writing-mode: sideways-rl; width: stretch; height: 20px;">16</div>
</div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="49"
data-offset-y="1"
style="writing-mode: sideways-lr; width: 20px; height: stretch;">17</div>
</div>
<div class="container" style="border-top: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="1"
style="writing-mode: sideways-lr; width: stretch; height: 20px;">18</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="20" data-expected-height="50"
data-offset-y="0"
style="writing-mode: sideways-lr; width: 20px; height: stretch;">19</div>
</div>
<div class="container" style="border-right: 5px solid;">
<div class="child" data-expected-width="40" data-expected-height="20"
data-offset-y="0"
style="writing-mode: sideways-lr; width: stretch; height: 20px;">20</div>
</div>

<script>
checkLayout('.child');
</script>
Loading

0 comments on commit a220728

Please sign in to comment.