-
Notifications
You must be signed in to change notification settings - 8000 Fork 707
/
Copy pathOverview.bs
1185 lines (985 loc) · 40.7 KB
/
Overview.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class=metadata>
Title: CSS Containment Module Level 3
Level: 3
Shortname: css-contain
Status: ED
Prepare for TR: no
Work Status: Revising
Group: csswg
ED: https://drafts.csswg.org/css-contain-3/
TR: https://www.w3.org/TR/css-contain-3/
Previous Version: https://www.w3.org/TR/2021/WD-css-contain-3-20211221/
Editor: Tab Atkins, Google, http://xanthir.com/contact/, w3cid 42199
Editor: Florian Rivoal, On behalf of Bloomberg, https://florian.rivoal.net/, w3cid 43241
Editor: Miriam E. Suzanne, Invited Expert, https://www.miriamsuzanne.com/who/, w3cid 117151
Abstract: This CSS module describes the 'contain' property, which indicates that the element’s subtree is independent of the rest of the page. This enables heavy optimizations by user agents when used well.
Test Suite: https://test.csswg.org/harness/results/css-contain-1_dev/
</pre>
<pre class=link-defaults>
spec:css2; type:dfn; text:stacking context
spec:css2; type:property; text:content
spec:css-display-3; type:property; text:display
spec:css2; type:property; text:counter-increment
spec:css-ui-3; type:property; text:text-overflow
spec:css-grid-1; type:property; text:grid
spec:css-break-3; type:dfn; text:forced break
spec:css-break-3; type:dfn; text:fragmentation
spec:css-break-3; type:dfn; text:fragmentation container
spec:css-break-3; type:dfn; text:fragmentation context
spec:css-break-3; type:dfn; text:fragmented flow
spec:css-contain-2; type:dfn; text:layout containment box
spec:css-contain-2; type:dfn; text:size containment box
spec:css-pseudo-4; type:dfn; text:fictional tag sequence
spec:css-sizing-4; type:property; text:contain-intrinsic-size
spec:css-sizing-4; type:property; text:aspect-ratio
spec:intersection-observer; type:dfn; text:intersection root
spec:css-sizing-3; type:property;
text:min-width
text:min-height
spec:css-sizing-3; type:dfn; text:width
spec:css-sizing-3; type:property; text:height
spec:css-sizing-3; type:dfn; text:height
spec:css-sizing-3; type:dfn; text:size
spec:css-values-4; type:dfn; text:relative length
spec:css-values-4; type:dfn; text:identifier
spec:web-animations-1; type:dfn; text:effect values
</pre>
<h2 id='intro'>
Introduction</h2>
Issue: This is a diff spec over <a href="https://www.w3.org/TR/css-contain-2/">CSS Containment Level 2</a>.
It is currently an Exploratory Working Draft:
if you are implementing anything, please use Level 2 as a reference.
We will merge the Level 2 text into this draft once it reaches CR.
<h3 id="interaction">
Module Interactions</h3>
This document defines new features not present in earlier specifications.
In addition, it aims to replace and supersede [[!CSS-CONTAIN-1]]
once stable.
<h3 id="values">
Value Definitions</h3>
This specification follows the <a href="https://www.w3.org/TR/CSS2/about.html#property-defs">CSS property definition conventions</a> from [[!CSS2]]
using the <a href="https://www.w3.org/TR/css-values-3/#value-defs">value definition syntax</a> from [[!CSS-VALUES-3]].
Value types not defined in this specification are defined in CSS Values & Units [[!CSS-VALUES-3]].
Combination with other CSS modules may expand the definitions of these value types.
In addition to the property-specific values listed in their definitions,
all properties defined in this specification
also accept the <a>CSS-wide keywords</a> as their property value.
For readability they have not been repeated explicitly.
<h2 id='contain-property'>
Strong Containment: the 'contain' property</h2>
Issue: [[css-contain-2#contain-property]]
<pre class='propdef partial'>
Name: contain
New Values: layout || style || paint || [ size | inline-size ]
</pre>
<dl dfn-type=value dfn-for=contain>
<dt><dfn>inline-size</dfn>
<dd>
This value turns on [=inline-size containment=] for the element.
This prevents the [=inline-size=] of its [=principal box=]
from directly depending on its contents.
Note: There can still be indirect dependencies,
see [[#containment-inline-size]].
</dl>
<h2 id='containment-types'>
Types of Containment</h2>
Issue: [[css-contain-2#containment-types]]
<h3 id='containment-inline-size'>
Inline-Size Containment</h3>
Giving an element <dfn export>inline-size containment</dfn>
applies [=size containment=] to the [=inline-axis=] sizing of its [=principal box=].
This means the [=inline-axis=] [=intrinsic sizes=] of the [=principal box=]
are determined as if the element had no content.
However, content continues to impact the box’s [=block-axis=] [=intrinsic sizes=] as usual,
and the box is allowed to [=fragmentation|fragment=] normally in the [=block axis=].
<div class=note>
<span class="marker">Note:</span> In some cases,
a box’s [=block-axis=] [=intrinsic sizes=]
can impact layout in the parent [=formatting context=]
in ways that affect the box’s [=inline size=]
(e.g. by triggering scrollbars on an ancestor element),
creating a dependency of the box’s [=inline size=] on its own content.
If this changed [=inline size=] results in a different [=block size=],
that new [=block size=] can loop into further impacting the parent formatting context,
but not in a way that reverts it to the previously-problematic layout.
For example, if scrollbars were introduced,
they are not then removed,
even if the consequent [=block size=] is small enough to not need them;
or if a box’s logical height collides with a lower-placed float and is cleared down
to where it also has more available inline space
and thus becomes short enough to not have collided,
it is not them moved back up to its previous problematic size and position.
Thus, although [=inline-size containment=] prevents
the box’s content from directly affecting its [=inline size=]
through its [=inline-axis=] [=intrinsic sizes=],
its [=inline size=] can still indirectly depend on its contents
by their effect on its [=block size=].
</div>
ISSUE:
In general, the relationship between an element's inline size
and it's block size
is unpredictable and non-monotonic,
with the block size capable of shifting up and down arbitrarily
as the inline size is changed.
Infinite cycles are prevented
by ensuring that layout does not revert to a previous (known-problematic) state,
even if a naive analysis of the constraints would allow for such;
in other words, layout always “moves forward”.
We believe that current CSS layout specifications incorporate such rules,
but to the extent that they don't,
please <a href="https://github.com/w3c/csswg-drafts/issues">inform the CSSWG</a>
so that these errors can be corrected.
<div class=example>
Consider this example,
where float placement creates a dependency of block sizes on inline sizes:
<xmp class=lang-markup>
<section style="width: 200px; border: solid; display: flow-root;">
<!-- floated elements that impact the available space -->
<div style="float: left; width: 50px; height: 80px; background: blue;"></div>
<div style="float: right; width: 50px; height: 80px; background: blue;"></div>
<div style="float: left; width: 160px; height: 80px; background: navy;"></div>
<!-- parent layout, determining context -->
<article style="border: solid orangered; display: flow-root; min-width: min-content">
<div style="background: orange; aspect-ratio: 1/1;">
Article
</div>
</article>
</section>
</xmp>
<figure style="float: left; margin: 1em 0.5em">
<section style="width: 200px; border: solid; display: flow-root;">
<!-- floated elements that impact the available space -->
<div style="float: left; width: 50px; height: 80px; background: blue;"></div>
<div style="float: right; width: 50px; height: 80px; background: blue;"></div>
<div style="float: left; width: 160px; height: 80px; background: navy;"></div>
<!-- parent layout, determining context -->
<article style="border: solid orangered; display: flow-root; min-width: 50px">
<div style="background: orange; aspect-ratio: 1/1;">
Article
</div>
</article>
</section>
</figure>
The block layout algorithm will first place the floating boxes,
with the first two sitting in the left and right corners of the container,
and the third, being too wide to fit between, being pushed below them.
The following <code>article</code> will then be laid out.
Because it is ''display: flow-root'',
it cannot intersect any floats,
and thus must take them into account
when figuring out how to size and position itself.
The layout engine first attempts to place the <code>article</code>
flush with the top of the container,
resulting a ''100px'' width,
plenty wide enough to accommodate its [=min-content size=].
However, due to the 'aspect-ratio' of its child,
this would cause the <code>article</code> to be ''100px'' tall as well,
which would intersect the third float 80px below,
FE66
div>
so this layout opportunity is discarded.
It then attempts to position the <code>article</code>
flush with the top of the third float,
in the narrow ''40px''-wide space to its right.
However, since the <code>article</code>’s 'min-width' makes it too large
to fit in the 40px-wide space beside the third float,
it shifts below that one as well,
forming a 200px square below all the floated boxes.
<figure style="float: right; margin: 1em 0.5em">
<section style="width: 200px; border: solid; display: flow-root;">
<!-- floated elements that impact the available space -->
<div style="float: left; width: 50px; height: 80px; background: blue;"></div>
<div style="float: right; width: 50px; height: 80px; background: blue;"></div>
<div style="float: left; width: 160px; height: 80px; background: navy;"></div>
<!-- parent layout, determining context -->
<article style="border: solid orangered; display: flow-root;">
<div style="background: orange; aspect-ratio: 1/1;">
Article
</div>
</article>
</section>
</figure>
If the 'min-width' is removed from the <code>article</code>,
or if [=inline-size containment=] is added to
either the <code>article</code> or <code>header</code>
(causing ''min-width: min-content'' to resolve to zero),
then the <code>article</code> will fit as a 40px square
next to the final floated <code>div</code>
(possibly with some of its content overflowing).
At this point, the width and height of the <code>article</code>
(''40px'' each)
<em>would</em> fit back in the first considered space,
flush with the top of the container.
However, the box is not returned to the previous position,
because the layout engine knows already
that this position would result in an invalid layout.
</div>
Giving an element [=inline-size containment=]
has no effect if any of the following are true:
* if the element does not generate a <a>principal box</a>
(as is the case with ''display: contents'' or ''display: none'')
* if its [=inner display type=] is ''display/table''
* if its [=principal box=] is
an <a spec="css-display-3">internal table box</a>
* if its [=principal box=] is
an <a spec="css-display-3">internal ruby box</a>
or a <a spec="css-display-3" lt="atomic inline">non-atomic</a> <a spec="css-display-3">inline-level</a> box
<h2 id="container-queries">
Container Queries</h2>
While [=media queries=] provide a method to query
aspects of the user agent or device environment
that a document is being displayed in
(such as viewport dimensions or user preferences),
[=container queries=] allow testing aspects of elements within the document
(such as box dimensions or computed styles).
By default, all elements are [=query containers=]
for the purpose of [=container style queries=],
and can be established as [=query containers=]
for [=container size queries=] by specifying
the additional query types using the 'container-type' property
(or the 'container' [=shorthand=]).
Style rules applying to a [=query container=]’s <a>shadow-including descendants</a>
can be conditioned by querying against it,
using the ''@container'' [=conditional group rule=].
<div class=example>
For example, we can define the main content area and sidebar as containers,
and then describe a ''.media-object'' that changes
from vertical to horizontal layout depending on the size of its container:
<pre class=lang-css>
main, aside {
container: my-layout / inline-size;
}
.media-object {
display: grid;
grid-template: 'img' auto 'content' auto / 100%;
}
@container my-layout (inline-size > 45em) {
.media-object {
grid-template: 'img content' auto / auto 1fr;
}
}
</pre>
Media objects in the main and sidebar areas
will each respond to their own container context.
</div>
For selectors with pseudo elements, query containers can be established by
the <a>shadow-including inclusive ancestors</a> of the <a>ultimate
originating element</a>.
<div class=note>
It follows that:
* Pseudo elements themselves can not be query containers
* ''::before'', ''::after'', ''::marker'', and ''::backdrop'' query their
originating elements
* ''::first-letter'' and ''::first-line'' query their originating elements,
even if the <a>fictional tag sequence</a> may push the
<code>::first-line</code> past other elements for the purpose of
inheritance and rendering
* Multiple pseudo elements do not allow pseudo elements to be query
containers for other pseudo elements. E.g., the host, but not the
<code>::part()</code>, can be the query container for
<code>::before</code> in <code>host::part()::before</code>. Similarly,
<code>::before</code> can not be the query container for the
<code>::marker</code> in <code>div::before::marker</code>
* ''::slotted()'' selectors can query containers inside the shadow tree,
including the slot itself
* ''::part()'' selectors can query its originating host, but not internal
query containers inside the shadow tree
* ''::placeholder'' and ''::file-selector-button'' can query the input
element, but do not expose any internal containers if the input element is
implemented using a shadow tree
</div>
<div class=example>
A ::before selector querying the size of the originating element:
<pre class=lang-html>
<style>
#container {
width: 100px;
container-type: inline-size;
}
@container (inline-size < 150px) {
#inner::before {
content: "BEFORE";
}
}
</style>
<div id=container>
<span id=inner></span>
</div>
</pre>
</div>
<div class=example>
A ::slotted() selector for styling a shadow host child can query a
container in the shadow tree:
<pre class=lang-html>
<div id=host style="width:200px">
<template shadowroot=open>
<style>
#container {
width: 100px;
container-type: inline-size;
}
@container (inline-size < 150px) {
::slotted(span) {
color: green;
}
}
</style>
<div id=container>
<slot />
</div>
</template>
<span id=slotted>Green</span>
</div>
</pre>
</div>
<h3 id="container-type">
Creating Query Containers: the 'container-type' property</h3>
<pre class='propdef'>
Name: container-type
Value: normal | size | inline-size
Initial: normal
Inherited: no
Applies to: all elements
Computed value: the keyword ''container-type/normal'' or one or more of ''container-type/size'', ''container-type/inline-size''
Animation type: not animatable
</pre>
The 'container-type' property establishes the element
as a <dfn export>query container</dfn>
for the purpose of [=container queries=] that require explicit containment
(such as [=container size queries=]),
allowing [=style rules=] styling its descendants
to query various aspects of its sizing and layout,
and respond accordingly.
Unless otherwise noted,
all elements are [=query containers=]
for the purpose of [=container queries=]
that do not require explicit [=containment=]
(such as [=container style queries=]),
regardless of the specified 'container-type'.
Values have the following meanings:
<dl dfn-type=value dfn-for=container-type>
<dt><dfn>size</dfn>
<dd>
Establishes a [=query container=] for [=container size queries=]
on both the [=inline axis|inline=] and [=block axis=].
Applies [=layout containment=],
[=style containment=],
and [=size containment=]
to the [=principal box=].
<dt><dfn>inline-size</dfn>
<dd>
Establishes a [=query container=] for [=container size queries=]
on the container’s own [=inline axis=].
Applies [=layout containment=],
[=style containment=],
and [=inline-size containment=]
to the [=principal box=].
<dt><dfn>normal</dfn>
<dd>
The element is not a [=query container=]
for any [=container size queries=],
but remains a [=query container=] for [=container style queries=].
</dl>
<div class=example>
For example, authors can create container-responsive typography,
adjusting 'font-size', 'line-height', and other typographic concerns
based on the size of a container:
<pre class=lang-css>
aside, main {
container-type: inline-size;
}
h2 { font-size: 1.2em; }
@container (width > 40em) {
h2 { font-size: 1.5em; }
}
</pre>
The ''40em'' value used in the query condition
is relative to the [=computed value=] of 'font-size'
on the relevant [=query container=].
</div>
<div class=example>
Containers can also expose computed style values for querying.
This can be useful for toggling behavior across multiple properties:
<pre class=lang-css>
section {
container-type: style;
}
@container (--cards: small) {
article {
border: thin solid silver;
border-radius: 0.5em;
padding: 1em;
}
}
</pre>
</div>
<h3 id="container-name">
Naming Query Containers: the 'container-name' property</h3>
<pre class='propdef'>
Name: container-name
Value: none | <<custom-ident>>+
Initial: none
Inherited: no
Applies to: all elements
Computed Value: the keyword ''container-name/none'', or an ordered list of [=identifiers=]
Animation type: not animatable
</pre>
The 'container-name' property
specifies a list of <dfn export lt="query container name">query container names</dfn>.
These names can be used by ''@container'' rules
to filter which [=query containers=] are targeted.
<dl dfn-for=container-name dfn-type=value>
<dt><dfn>none</dfn>
<dd>
The [=query container=] has no [=query container name=].
<dt><dfn><<custom-ident>></dfn>
<dd>
Specifies a [=query container name=] as an [=identifier=].
The keywords ''container-name/none'', ''and'', ''not'', and ''or'' are excluded from this <<custom-ident>>.
</dl>
<div class=example>
In some cases, we want to query aspects of a specific container,
even if it’s not the nearest ancestor container.
For example, we might want to query the height of a main content area,
and the width of a more nested inline-container.
<pre class=lang-css>
main {
container-type: size;
container-name: my-page-layout;
}
.my-component {
container-type: inline-size;
container-name: my-component-library;
}
@container my-page-layout (block-size > 12em) {
.card { margin-block: 2em; }
}
@container my-component-library (inline-size > 30em) {
.card { margin-inline: 2em; }
}
</pre>
</div>
<h3 id="container-shorthand">
Creating Named Containers: the 'container' shorthand</h3>
<pre class='propdef shorthand'>
Name: container
Value: <<'container-name'>> [ / <<'container-type'>> ]?
</pre>
The 'container' [=shorthand property=] sets
both 'container-type' and 'container-name' in the same declaration.
If <<'container-type'>> is omitted,
it is reset to its [=initial value=].
<div class=example>
We can define both a 'container-type' and 'container-name'
using the shorthand syntax:
<pre class=lang-css>
main {
container: my-layout / size;
}
.grid-item {
container: my-component / inline-size;
}
</pre>
</div>
<h3 id="container-rule">
Container Queries: the ''@container'' rule</h3>
The <dfn at-rule id="at-ruledef-container">@container</dfn> rule
is a [=conditional group rule=] whose condition contains
a <dfn export>container query</dfn>,
which is a boolean combination of [=container size queries=] and/or [=container style queries=].
Style declarations within the <<stylesheet>> block of an ''@container'' rule
are [[css-cascade-4#filtering|filtered]] by its condition
to only match when the [=container query=]
is true for their element’s [=query container=].
The syntax of the ''@container'' rule is:
<pre class="prod def">
@container <<container-condition>> {
<<stylesheet>>
}
</pre>
where:
<pre class="prod def">
<dfn><<container-condition>></dfn> = [ <<container-name>> ]? <<container-query>>
<dfn><<container-name>></dfn> = <<custom-ident>>
<dfn><<container-query>></dfn> = not <<query-in-parens>>
| <<query-in-parens>> [ [ and <<query-in-parens>> ]* | [ or <<query-in-parens>> ]* ]
<dfn><<query-in-parens>></dfn> = ( <<container-query>> )
| ( <<size-feature>> )
| style( <<style-query>> )
| <<general-enclosed>>
<dfn><<style-query>></dfn> = not <<style-in-parens>>
| <<style-in-parens>> [ [ and <<style-in-parens>> ]* | [ or <<style-in-parens>> ]* ]
| <<style-feature>>
<dfn><<style-in-parens>></dfn> = ( <<style-query>> )
| ( <<style-feature>> )
| <<general-enclosed>>
</pre>
The keywords ''container-name/none'', ''and'', ''not'', and ''or''
are excluded from the <<custom-ident>> above.
For each element,
the [=query container=] to be queried
is selected from among the element’s ancestor [=query containers=]
that are established as a valid [=query container=]
for all the [=container features=]
in the <<container-query>>.
The optional <<container-name>>
filters the set of [=query containers=] considered
to just those with a matching [=query container name=].
Once an eligible [=query container=] has been selected for an element,
each [=container feature=] in the <<container-query>>
is evaluated against that [=query container=].
If no ancestor is an eligible [=query container=],
then the [=container query=] is ''unknown'' for that element.
<div class=example>
As with [=media queries=],
we can string together multiple conditions in a single query list:
<pre class=lang-css>
@container card (inline-size > 30em) and style(--responsive: true) {
/* styles */
}
</pre>
The styles above will only be applied
if there is an ancestor container named "card"
that meets both the '@container/inline-size'
and [=container style query|style=] conditions.
</div>
Style rules defined on an element inside multiple nested [=container queries=]
apply when all of the wrapping [=container queries=] are true for that element.
Note: Nested [=container queries=] can evaluate in relation to different containers,
so it is not always possible to merge the individual <<container-condition>>s
into a single query.
<div class=example>
While it is not possible to query multiple containers
in a single [=container query=],
that can be achieved by nesting multiple queries:
<pre class=lang-css>
@container card (inline-size > 30em) {
@container style(--responsive: true) {
/* styles */
}
}
</pre>
The styles above will only be applied
if there is an ancestor container named "card"
that meets the '@container/inline-size' condition,
as well as an ancestor container
meeting [=container style query|style=] condition.
</div>
Global, name-defining [=at-rules=]
such as ''@keyframes'' or ''@font-face'' or ''@layer''
that are defined inside [=container queries=]
are not constrained by the [=container query=] conditions.
<h3 id="animated-containers">
Animated Containers</h3>
A change in the evaluation of a [=container query=] must be part of a [=style change event=],
even when the change occurred because of [=effect values|animation effects=].
<div class=example>
A transition on a sibling element can indirectly affect the size of a
container, triggering [=style change events=] whenever container queries
change their evaluation as a result:
<pre class=lang-css>
main {
display: flex;
width: 300px;
}
#container {
container-type: inline-size;
flex: 1;
}
/* Resolved width is initially 200px, but changes as the transition
on #sibling progresses. */
#inner {
transition: 1s background-color;
background-color: tomato;
}
/* When this container query starts (or stops) applying, a transition
must start on background-color on #inner. */
@container (width <= 150px) {
#inner {
background-color: skyblue;
}
}
#sibling {
width: 100px;
transition: width 1s;
}
#sibling:hover {
width: 200px;
}
</pre>
<pre class=lang-html>
<main>
<div id=container>
<div id=inner>Inner</div>
</div>
<div id=sibling>Sibling</div>
</main>
</pre>
</div>
Changes in [=computed values=] caused by [=container query length=] units
must also be part of a [=style change event=].
<h2 id="container-features">
Container Features</h2>
A <dfn export>container feature</dfn>
queries a specific aspect of a [=query container=].
<h3 id="size-container">
Size Container Features</h3>
A <dfn export>container size query</dfn>
allows querying
the size of the [=query container=]’s [=principal box=].
It is a boolean combination of
individual <dfn>size features</dfn> (<<size-feature>>)
that each query a single, specific dimensional feature of the [=query container=].
The syntax of a <dfn><<size-feature>></dfn> is the same as for a [=media feature=]:
a feature name, a comparator, and a value.
[[mediaqueries-5]]
The boolean syntax and logic combining [=size features=] into a [=container size query|size query=]
is the same as for [=CSS feature queries=].
(See ''@supports''. [[!CSS-CONDITIONAL-3]])
If the [=query container=] does not have a [=principal box=],
or the principal box is not a [=layout containment box=],
or the [=query container=] does not support [=container size queries=] on the relevant axes,
then the result of evaluating the [=size feature=] is unknown.
[=Relative length=] units
(including [=container query length=] units)
in [=container query=] conditions
are evaluated based on the the [=computed values=] of the [=query container=].
Note: This is different from the handling of relative units in [=media queries=].
<div class=example>
For example, [=query containers=] with different font-sizes
will evaluate ''em''-based queries relative to their own font sizes:
<pre class=lang-css>
aside, main {
container-type: inline-size;
}
aside { font-size: 16px; }
main { font-size: 24px; }
@container (width > 40em) {
h2 { font-size: 1.5em; }
}
</pre>
The ''40em'' value used in the query condition
is relative to the [=computed value=] of 'font-size'
on the relevant [=query container=]:
* For any ''h2'' inside ''aside'',
the query condition will be true above ''640px''.
* For any ''h2'' inside ''main'',
the query condition will be true above ''960px''.
</div>
<h4 id="width">
Width: the '@container/width' feature</h4>
<pre class="descdef mq">
Name: width
For: @container
Value: <<length>>
Type: range
</pre>
The '@container/width' [=container feature=]
queries the [=width=]
of the [=query container=]’s [=content box=].
<h4 id="height">
Height: the '@container/height' feature</h4>
<pre class="descdef mq">
Name: height
For: @container
Value: <<length>>
Type: range
</pre>
The '@container/height' [=container feature=]
queries the [=height=]
of the [=query container=]’s [=content box=].
<h4 id="inline-size">
Inline-size: the '@container/inline-size' feature</h4>
<pre class="descdef mq">
Name: inline-size
For: @container
Value: <<length>>
Type: range
</pre>
The '@container/inline-size' [=container feature=]
queries the [=size=]
of the [=query container=]’s [=content box=]
in the [=query container=]’s [=inline axis=].
<h4 id="block-size">
Block-size: the '@container/block-size' feature</h4>
<pre class="descdef mq">
Name: block-size
For: @container
Value: <<length>>
Type: range
</pre>
The '@container/block-size' [=container feature=]
queries the [=size=]
of the [=query container=]’s [=content box=]
in the [=query container=]’s [=block axis=].
<h4 id="aspect-ratio">
Aspect-ratio: the '@container/aspect-ratio' feature</h4>
<pre class="descdef mq">
Name: aspect-ratio
For: @container
Value: <<ratio>>
Type: range
</pre>
The '@container/aspect-ratio' [=container feature=] is defined as the ratio
of the value of the '@container/width' [=container feature=]
to the value of the '@container/height' [=container feature=].
<h4 id="orientation">
Orientation: the '@container/orientation' feature</h4>
<pre class="descdef mq">
Name: orientation
For: @container
Value: portrait | landscape
Type: discrete
</pre>
<dl dfn-type=value dfn-for="@container/orientation">
<dt><dfn>portrait</dfn>
<dd>
The '@container/orientation' [=container feature=] is ''portrait''
when the value of the '@container/height' [=container feature=]
is greater than or equal to
the value of the '@container/width' [=container feature=].
<dt><dfn>landscape</dfn>
<dd>Otherwise '@container/orientation' is ''landscape''.
</dl>
<h3 id="style-container">
Style Container Features</h3>
A <dfn export>container style query</dfn>
allows querying
the [=computed values=] of the [=query container=].
It is a boolean combination of
individual <dfn>style features</dfn> (<<style-feature>>)
that each query a single, specific property of the [=query container=].
The syntax of a <dfn><<style-feature>></dfn> is the same as for a [=declaration=]
[[!CSS-SYNTAX-3]],
and its query is true if
the [=computed value=] of the given property on the [=query container=]
matches the given value
(which is also [=computed value|computed=] with respect to the [=query container=]),
unknown if the property or its value is invalid or unsupported,
and false otherwise.
The boolean syntax and logic combining [=style features=] into a [=container style query|style query=]
is the same as for [=CSS feature queries=].
(See ''@supports''. [[!CSS-CONDITIONAL-3]])
[=Style features=] that query a [=shorthand property=] are true if the
[=computed values=] match for each of its [=longhand properties=],
and false otherwise.
[=Cascade-dependent keywords=], such as ''revert'' and ''revert-layer'',
are invalid as values in a [=style feature=], and cause the
[=container style query=] to be false.
Note: The remaining non-cascade-dependent [=CSS-wide keywords=]
are [=computed value|computed=] with respect to the [=query container=],
the same as other values.
<h2 id="container-lengths">
Container Relative Lengths: the ''cqw'', ''cqh'', ''cqi'', ''cqb'', ''cqmin'', ''cqmax'' units</h2>
<dfn lt="container query length">Container query length units</dfn>
specify a length relative to the dimensions of a [=query container=].
Style sheets that use [=container query length=] units can more easily move components
from one [=query container=] to another.
The [=container query length=] units are:
<table class="data">
<caption>Informative Summary of Container Units</caption>
<thead>
<tr><th>unit<th>relative to
</thead>
<tbody>
<tr><td>''cqw''
<td>1% of a [=query container=]’s [=width=]
<tr><td>''cqh''
<td>1% of a [=query container=]’s [=height=]
<tr><td>''cqi''
<td>1% of a [=query container=]’s [=inline size=]
<tr><td>''cqb''
<td>1% of a [=query container=]’s [=block size=]
<tr><td>''cqmin''
<td>The smaller value of ''cqi'' or ''cqb''
<tr><td>''cqmax''
<td>The larger value of ''cqi'' or ''cqb''
</tbody>
</table>
For each element,
[=container query length=] units are evaluated
as [=container size queries=] on the relevant axis (or axes)
described by the unit.
The [=query container=] for each axis
is the nearest ancestor container
that accepts [=container size queries=] on that axis.
If no eligible [=query container=] is available,
then use the [=small viewport size=] for that axis.
Note: In some cases ''cqi'' and ''cqb'' units on the same element
will evaluate in relation to different [=query containers=].
Similarly, ''cqmin'' and ''cqmax'' units represent
the larger or smaller of the ''cqi'' and ''cqb'' units,
even when those dimensions come from different [=query containers=].
Child elements do not inherit the relative values as specified for their parent;
they inherit the <a>computed values</a>.
<div class=example>
Authors can ensure that [=container query length=] units
have an appropriate [=query container=]
by applying them inside a [=container query=]
that relies on the same ''container-type''.
Custom fallback values can be defined outside the [=container query=]:
<pre class=lang-css>
/* The fallback value does not rely on containment */
h2 { font-size: 1.2em; }
@container (inline-size >= 0px) {
/* only applies when an inline-size container is available */
h2 { font-size: calc(1.2em + 1cqi); }
}
</pre>
</div>
<h2 id="apis">APIs</h2>