Skip to content

Commit cda4f34

Browse files
committed
[css-contain] Move inline-size containment from L2 to L3
See #10433
1 parent bdc1a95 commit cda4f34

File tree

2 files changed

+191
-204
lines changed

2 files changed

+191
-204
lines changed

css-contain-2/Overview.bs

+188-17
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ Strong Containment: the 'contain' property</h2>
107107

108108
<pre class='propdef'>
109109
Name: contain
110-
Value: none | strict | content | [ size || layout || style || paint ]
110+
Value: none | strict | content | [ [size | inline-size] || layout || style || paint ]
111111
Initial: none
112112
Inherited: no
113113
Applies to: See <a href="#contain-applies">below</a>
@@ -259,6 +259,34 @@ Strong Containment: the 'contain' property</h2>
259259
contain-size-grid-stretches-auto-rows.html
260260
</wpt>
261261

262+
<dt><dfn>inline-size</dfn>
263+
<dd>
264+
This value turns on [=inline-size containment=] for the element.
265+
This prevents the [=inline-size=] of its [=principal box=]
266+
from directly depending on its contents.
267+
268+
<wpt>
269+
contain-inline-size-bfc-floats-001.html
270+
contain-inline-size-bfc-floats-002.html
271+
contain-inline-size-fieldset.html
272+
contain-inline-size-flex.html
273+
contain-inline-size-flexitem.html
274+
contain-inline-size-grid.html
275+
contain-inline-size-intrinsic.html
276+
contain-inline-size-legend.html
277+
contain-inline-size-multicol.html
278+
contain-inline-size-regular-container.html
279+
contain-inline-size-removed.html
280+
contain-inline-size-replaced.html
281+
contain-inline-size-table.html
282+
contain-inline-size-vertical-rl-.html
283+
contain-inline-size-grid-indefinite-height-min-height-flex-row.html
284+
contain-inline-size-grid-stretches-auto-rows.html
285+
</wpt>
286+
287+
Note: There can still be indirect dependencies,
288+
see [[#containment-inline-size]].
289+
262290
<dt><dfn>layout</dfn>
263291
<dd>
264292
This value turns on <a>layout containment</a> for the element.
@@ -802,6 +830,165 @@ Possible Size-Containment Optimizations</h4>
802830
if the [=size containment box|containment box=] is off-screen or obscured,
803831
the layout of its contents (i.e. "[=laying out in-place=]") can be delayed or done at a lower priority.
804832

833+
<h3 id='containment-inline-size'>
834+
Inline-Size Containment</h3>
835+
836+
Giving an element <dfn export>inline-size containment</dfn>
837+
applies [=size containment=] to the [=inline-axis=] sizing of its [=principal box=].
838+
This means the [=inline-axis=] [=intrinsic sizes=] of the [=principal box=]
839+
are determined as if the element had no content.
840+
However, content continues to impact the box’s [=block-axis=] [=intrinsic sizes=] as usual,
841+
and the box is allowed to [=fragmentation|fragment=] normally in the [=block axis=].
842+
843+
<div class=note>
844+
<span class="marker">Note:</span> In some cases,
845+
a box’s [=block-axis=] [=intrinsic sizes=]
846+
can impact layout in the parent [=formatting context=]
847+
in ways that affect the box’s [=inline size=]
848+
(e.g. by triggering scrollbars on an ancestor element),
849+
creating a dependency of the box’s [=inline size=] on its own content.
850+
If this changed [=inline size=] results in a different [=block size=],
851+
that new [=block size=] can loop into further impacting the parent formatting context,
852+
but not in a way that reverts it to the previously-problematic layout.
853+
854+
For example, if scrollbars were introduced,
855+
they are not then removed,
856+
even if the consequent [=block size=] is small enough to not need them;
857+
or if a box’s logical height collides with a lower-placed float and is cleared down
858+
to where it also has more available inline space
859+
and thus becomes short enough to not have collided,
860+
it is not them moved back up to its previous problematic size and position.
861+
862+
Thus, although [=inline-size containment=] prevents
863+
the box’s content from directly affecting its [=inline size=]
864+
through its [=inline-axis=] [=intrinsic sizes=],
865+
its [=inline size=] can still indirectly depend on its contents
866+
by their effect on its [=block size=].
867+
</div>
868+
869+
ISSUE:
870+
In general, the relationship between an element's inline size
871+
and it's block size
872+
is unpredictable and non-monotonic,
873+
with the block size capable of shifting up and down arbitrarily
874+
as the inline size is changed.
875+
Infinite cycles are prevented
876+
by ensuring that layout does not revert to a previous (known-problematic) state,
877+
even if a naive analysis of the constraints would allow for such;
878+
in other words, layout always “moves forward”.
879+
We believe that current CSS layout specifications incorporate such rules,
880+
but to the extent that they don't,
881+
please <a href="https://github.com/w3c/csswg-drafts/issues">inform the CSSWG</a>
882+
so that these errors can be corrected.
883+
884+
<div class=example>
885+
Consider this example,
886+
where float placement creates a dependency of block sizes on inline sizes:
887+
888+
<xmp class=lang-markup>
889+
<section style="width: 200px; border: solid; display: flow-root;">
890+
<!-- floated elements that impact the available space -->
891+
<div style="float: left; width: 50px; height: 80px; background: blue;"></div>
892+
<div style="float: right; width: 50px; height: 80px; background: blue;"></div>
893+
<div style="float: left; width: 160px; height: 80px; background: navy;"></div>
894+
895+
<!-- parent layout, determining context -->
896+
<article style="border: solid orangered; display: flow-root; min-width: min-content">
897+
<div style="background: orange; aspect-ratio: 1/1;">
898+
Article
899+
</div>
900+
</article>
901+
</section>
902+
</xmp>
903+
904+
<figure style="float: left; margin: 1em 0.5em">
905+
<section style="width: 200px; border: solid; display: flow-root;">
906+
<!-- floated elements that impact the available space -->
907+
<div style="float: left; width: 50px; height: 80px; background: blue;"></div>
908+
<div style="float: right; width: 50px; height: 80px; background: blue;"></div>
909+
<div style="float: left; width: 160px; height: 80px; background: navy;"></div>
910+
911+
<!-- parent layout, determining context -->
912+
<article style="border: solid orangered; display: flow-root; min-width: 50px">
913+
<div style="background: orange; aspect-ratio: 1/1;">
914+
Article
915+
</div>
916+
</article>
917+
</section>
918+
</figure>
919+
920+
The block layout algorithm will first place the floating boxes,
921+
with the first two sitting in the left and right corners of the container,
922+
and the third, being too wide to fit between, being pushed below them.
923+
924+
The following <code>article</code> will then be laid out.
925+
Because it is ''display: flow-root'',
926+
it cannot intersect any floats,
927+
and thus must take them into account
928+
when figuring out how to size and position itself.
929+
930+
The layout engine first attempts to place the <code>article</code>
931+
flush with the top of the container,
932+
resulting a ''100px'' width,
933+
plenty wide enough to accommodate its [=min-content size=].
934+
However, due to the 'aspect-ratio' of its child,
935+
this would cause the <code>article</code> to be ''100px'' tall as well,
936+
which would intersect the third float 80px below,
937+
so this layout opportunity is discarded.
938+
939+
It then attempts to position the <code>article</code>
940+
flush with the top of the third float,
941+
in the narrow ''40px''-wide space to its right.
942+
However, since the <code>article</code>’s 'min-width' makes it too large
943+
to fit in the 40px-wide space beside the third float,
944+
it shifts below that one as well,
945+
forming a 200px square below all the floated boxes.
946+
947+
<figure style="float: right; margin: 1em 0.5em">
948+
<section style="width: 200px; border: solid; display: flow-root;">
949+
<!-- floated elements that impact the available space -->
950+
<div style="float: left; width: 50px; height: 80px; background: blue;"></div>
951+
<div style="float: right; width: 50px; height: 80px; background: blue;"></div>
952+
<div style="float: left; width: 160px; height: 80px; background: navy;"></div>
953+
954+
<!-- parent layout, determining context -->
955+
<article style="border: solid orangered; display: flow-root;">
956+
<div style="background: orange; aspect-ratio: 1/1;">
957+
Article
958+
</div>
959+
</article>
960+
</section>
961+
</figure>
962+
963+
If the 'min-width' is removed from the <code>article</code>,
964+
or if [=inline-size containment=] is added to
965+
either the <code>article</code> or <code>header</code>
966+
(causing ''min-width: min-content'' to resolve to zero),
967+
then the <code>article</code> will fit as a 40px square
968+
next to the final floated <code>div</code>
969+
(possibly with some of its content overflowing).
970+
971+
At this point, the width and height of the <code>article</code>
972+
(''40px'' each)
973+
<em>would</em> fit back in the first considered space,
974+
flush with the top of the container.
975+
However, the box is not returned to the previous position,
976+
because the layout engine knows already
977+
that this position would result in an invalid layout.
978+
</div>
979+
980+
Giving an element [=inline-size containment=]
981+
has no effect if any of the following are true:
982+
983+
* if the element does not generate a <a>principal box</a>
984+
(as is the case with ''display: contents'' or ''display: none'')
985+
* if its [=inner display type=] is ''display/table''
986+
* if its [=principal box=] is
987+
an <a spec="css-display-3">internal table box</a>
988+
* if its [=principal box=] is
989+
an <a spec="css-display-3">internal ruby box</a>
990+
or a <a spec="css-display-3" lt="atomic inline">non-atomic</a> <a spec="css-display-3">inline-level</a> box
991+
805992
<h3 id='containment-layout'>
806993
Layout Containment</h3>
807994

@@ -2500,20 +2687,6 @@ Changes from <a href="https://www.w3.org/TR/css-contain-1/">CSS Containment Leve
25002687

25012688
<!-- catch all for tests only relevant to the css-contain-3, to stop bikeshed from complaining -->
25022689
<wpt>
2503-
contain-inline-size-bfc-floats-001.html
2504-
contain-inline-size-bfc-floats-002.html
2505-
contain-inline-size-fieldset.html
2506-
contain-inline-size-flex.html
2507-
contain-inline-size-flexitem.html
2508-
contain-inline-size-grid.html
2509-
contain-inline-size-intrinsic.html
2510-
contain-inline-size-legend.html
2511-
contain-inline-size-multicol.html
2512-
contain-inline-size-regular-container.html
2513-
contain-inline-size-removed.html
2514-
contain-inline-size-replaced.html
2515-
contain-inline-size-table.html
2516-
contain-inline-size-vertical-rl-.html
25172690
container-queries/animation-container-size.html
25182691
container-queries/animation-container-type-dynamic.html
25192692
container-queries/animation-nested-animation.html
@@ -2713,7 +2886,5 @@ container-queries/size-container-with-quotes.html
27132886
container-queries/style-container-for-shadow-dom.html
27142887
container-queries/style-container-invalidation-inheritance.html
27152888
container-queries/style-query-with-unknown-width.html
2716-
contain-inline-size-grid-indefinite-height-min-height-flex-row.html
2717-
contain-inline-size-grid-stretches-auto-rows.html
27182889
container-type-important.html
27192890
</wpt>

0 commit comments

Comments
 (0)