Skip to content

Commit

Permalink
[css-sizing-4] Rewrite the 'stretch-fit sizing' section to match WG r…
Browse files Browse the repository at this point in the history
…esolution. #11044
  • Loading branch information
tabatkins committed Feb 20, 2025
1 parent f170bb8 commit 15faddb
Showing 1 changed file with 65 additions and 50 deletions.
115 changes: 65 additions & 50 deletions css-sizing-4/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -836,65 +836,80 @@ 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=]
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.

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, ''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.

Note: Consequently, if neither ''align-self/stretch'' alignment applies
nor percentage sizing can resolve,
then the box will resolve to its [=automatic size=].
: If used in an axis where the relevant [=self-alignment property=] applies to the element
::
Produces the same size that would be obtained
by the [=self-alignment property=] in that axis
being set to ''justify-self/stretch''
and all [=sizing properties=] and 'aspect-ratio'
being set to their initial values.

: Otherwise, if used in an axis where percentage sizes can resolve to a [=definite=] value
::
Behaves as ''100%'',
except it sizes the [=margin box=]
regardless of the value of 'box-sizing'.

If this is a [=block axis=] size,
and the element is in a Block Layout [=formatting context=],
and the parent element does not have a [=block-start=] 'border' or 'padding'
and is not an [=independent formatting context=],
treat the element's [=block-start=] margin as zero
for the purpose of calculating this size.
Do the same for the [=block-end=] margin.

Note: This simulates the effect of margins collapsing with the parent's margin.
It doesn't actually suppress the margins,
so if anything prevents the element from actually collapsing with its parent,
the [=stretch-fit size=] might actually be too large
to fit in the parent perfectly.

<!--
Importantly, this *does* ensure that the stretch-fit size
doesn't depend on the presence or absence of other elements,
or the element's position among its siblings.
Multiple children with 'stretch' will all end up the same size.
-->

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

<div class="example">
For example, given the following HTML representing two [=block boxes=]:
<pre class=html>
&lt;div class="outer">
&lt;div class="inner">&lt;/div>
&lt;/div>
</pre>

<xmp class=html>
<div class="parent">
<div class="child">text</div>
</div>
</xmp>

In the following case,
the [=outer height=] of the inner box
will exactly match the height of the outer box (200px),
the [=outer height=] of the child box
will exactly match the height of the parent box (200px),
but its [=inner height=] will be 20px less, to account for its margins.

<pre>
.outer { height: 200px; border: solid; }
.inner { height: stretch; margin: 10px; }
.parent { height: 200px; border: solid; }
.child { height: stretch; margin: 10px; }
</pre>

In the following case,
the height of the inner box
will exactly match the height of the outer box (200px).
The top margins will collapse,
but the bottom margins do not collapse
(because the bottom margin of a box is not adjoining
to the bottom margin of a parent with a non-''height/auto'' height,
see [[CSS2/box#collapsing-margins]]),
and therefore the inner box’s bottom margin will be truncated.
On the other hand,
in this case we can assume that the child's margins will collapse with the parent,
so the inner box will be ''200px'' tall,
exactly filling the parent.

<pre>
.outer { height: 200px; margin: 0; }
.inner { height: stretch; margin: 10px; }
</pre>

(The top margins will in fact collapse,
but the bottom margins do not collapse,
because the bottom margin of a box is not adjoining
to the bottom margin of a parent with a non-''height/auto'' height,
see [[CSS2/box#collapsing-margins]].
Luckily, an overflowing bottom margin doesn't have any visible effect.)
</div>

<div class="example">
Expand All @@ -903,15 +918,15 @@ Stretch-fit Sizing: filling the containing block</h3>
(due to the 10px margin):

<pre class=html>
&lt;div class="outer">
&lt;div class="inner">text&lt;/div>
&lt;div class="parent">
&lt;div class="child">text&lt;/div>
&lt;/div>
some more text
</pre>

<pre>
.outer { float: left; margin: 0; }
.inner { width: stretch; margin: 10px; }
.parent { float: left; margin: 0; }
.child { width: stretch; margin: 10px; }
</pre>
</div>

Expand All @@ -922,8 +937,8 @@ Stretch-fit Sizing: filling the containing block</h3>
so ''height: stretch'' [=behaves as auto=] as well.

<pre>
.outer { height: auto; margin: 0; }
.inner { height: stretch; margin: 10px; }
.parent { height: auto; margin: 0; }
.child { height: stretch; margin: 10px; }
</pre>
</div>

Expand Down

0 comments on commit 15faddb

Please sign in to comment.