forked from w3c/csswg-drafts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOverview.bs
1493 lines (1241 loc) · 50.1 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 Conditional Rules Module Level 5
Group: csswg
Shortname: css-conditional
Level: 5
Status: ED
Prepare for TR: no
!Delta Spec: yes
Work Status: Exploring
ED: https://drafts.csswg.org/css-conditional-5/
TR: https://www.w3.org/TR/css-conditional-5/
Editor: L. David Baron, Mozilla https://www.mozilla.org/, https://dbaron.org/, w3cid 15393
Editor: Elika J. Etemad / fantasai, Apple, http://fantasai.inkedblade.net/contact, w3cid 35400
Editor: Chris Lilley, W3C, https://svgees.us/, w3cid 1438
Editor: Miriam E. Suzanne, Invited Expert, https://www.miriamsuzanne.com/who/, w3cid 117151
Abstract: This module contains the features of CSS
for conditional processing of parts of style sheets,
based on capabilities of the processor or the environment
the style sheet is being applied in.
It includes and extends the functionality of CSS Conditional 4 [[!css-conditional-4]],
adding the generalized conditional rule ''@when''
and the chained conditional rule ''@else'',
as well as introducing font processing queries
to the [=supports query=] syntax used in ''@supports'' rules,
and container queries.
Default Highlight: css
</pre>
<pre class="link-defaults">
spec: css-conditional-3
type: dfn; text: conditional group rule
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
spec:css-cascade-5; type:dfn; text:property
spec:css-values-4; type:type; text:<general-enclosed>
</pre>
<h2 id="introduction">
Introduction</h2>
ISSUE: This is currently an early draft of the things that are <em>new</em> in level 5.
The features in Level 3 and Level 4 are still defined
in [[css-conditional-3]] and [[css-conditional-4]]
and have not yet been copied here.
CSS Conditional Level 5 extends
the ''@supports'' rule and [=supports query=] syntax
to allow testing for supported font technologies.
It also adds an ''@when'' rule,
which generalizes the concept of a conditional rule.
Anything that can be expressed in an existing conditional rule
can be expressed in ''@when''
by wrapping it in an appropriate function
to declare what kind of condition it is.
This allow authors to easily combine multiple types of queries,
such as media queries and supports queries,
in a single boolean expression.
Without this,
authors must rely on nesting separate conditional rules,
which is harder to read and write,
presupposes the conditions are to be conjoined with the “and” boolean relation
(with no easy way to indicate anything else),
and restricts their utility in the proposed [=conditional rule chains=].
It also adds ''@else'' rules,
which immediately follow other conditional rules
and automatically qualify their conditions
as the inverse of the immediately preceding rule’s conditions,
such that only the first matching rule in a [=conditional rule chain=]
is applied.
It also adds Container Queries.
They are conceptually similar to Media Queries,
but allow testing aspects of elements within the document (such as box dimensions or computed styles),
rather than on the document as a whole.
<h2 id="at-supports-ext">
Extensions to the ''@supports'' rule</h2>
This level of the specification extends the <<supports-feature>> syntax as follows:
<pre class="prod def" nohighlight>
<dfn><supports-feature></dfn> = <<supports-selector-fn>> | <<supports-font-tech-fn>>
| <<supports-font-format-fn>> | <<supports-decl>>
<dfn><supports-font-tech-fn></dfn> = font-tech( <<font-tech>> )
<dfn><supports-font-format-fn></dfn> = font-format( <<font-format>> )
</pre>
: <<supports-font-tech-fn>>
::
The result is true if the UA
<a href="#dfn-support-font-tech">supports the font tech</a>
provided as an argument to the function.
: <<supports-font-format-fn>>
::
The result is true if the UA
<a href="#dfn-support-font-format">supports the font format</a>
provided as an argument to the function.
<h3 id="support-definition-ext">
Extensions to the definition of support</h3>
A CSS processor is considered to
<dfn export for=CSS id="dfn-support-font-tech">support a font tech</dfn>
when it is capable of utilizing the specified [[css-fonts-4#font-tech-definitions]]
in layout and rendering.
A CSS processor is considered to
<dfn export for=CSS id="dfn-support-font-format">support a font format</dfn>
when it is capable of utilizing the specified [[css-fonts-4#font-format-definitions]]
in layout and rendering,
and this format is not specified as a <<string>>.
<h2 id="when-rule">
Generalized Conditional Rules: the ''@when'' rule</h2>
The <dfn>@when</dfn> at-rule is a [=conditional group rule=]
that generalizes the individual [=conditional group rules=]
such as ''@media'' and ''@supports''.
It is defined as:
<pre class=prod>
@when <<boolean-condition>> {
<<rule-list>>
}
</pre>
Where <<boolean-condition>> is a boolean algebra a la [[mediaqueries-4#mq-syntax]],
but with ''media()'' and ''supports()'' functions as leaves.
Issue: Define "boolean algebra, with X as leaves" in a generic way in Conditional,
so all the conditional rules can reference it directly,
rather than having to redefine boolean algebra on their own.
The ''media()'' and ''supports()'' functions are defined as:
<pre class=prod>
<dfn>media()</dfn> = media( [ <<mf-plain>> | <<mf-boolean>> | <<mf-range>> ] )
<dfn>supports()</dfn> = supports( <<declaration>> )
</pre>
A ''media()'' or ''supports()'' function is associated the boolean result
that its contained condition is associated with.
<h2 id="else-rule">
Chained Conditionals: the ''@else'' rule</h2>
Usually, [=conditional group rules=] are independent;
each one has a separate condition
evaluated without direct reference to any other rule,
and decides whether or not to apply its contained rules
based solely on its condition.
This is fine for simple conditions,
but makes it difficult to write a collection of conditionals
that are meant to be mutually exclusive:
authors have to very carefully craft their conditions
to not activate when the other rules are meant to,
and make sure the collection of conditionals
don't accidentally <em>all</em> exclude some situation
which is then left unstyled.
The <dfn>@else</dfn> rule is a [=conditional group rule=]
used to form [=conditional rule chains=],
which associate multiple [=conditional rules=]
and guarantee that only the first one that matches
will evaluate its condition as true.
It is defined as:
<pre class=prod>
@else <<boolean-condition>>? {
<<rule-list>>
}
</pre>
''@else'' is interpreted identically to ''@when''.
If its <<boolean-condition>> is omitted,
it's treated as having a condition that's always true.
A <dfn export>conditional rule chain</dfn> is
a series of consecutive [=conditional group rules=],
starting with a [=conditional group rule=] other than ''@else'',
followed by zero or more ''@else'' rules.
There cannot be anything between the successive [=conditional group rules=]
other than whitespace and/or comments;
any other token “breaks” the chain.
Issue: Should we require that only the last ''@else'' in a chain can have an omitted condition?
It's not uncommon for me, when debugging code,
to short-circuit an if-else chain by setting one of them to "true";
I presume that would be similarly useful in CSS?
It's still pretty easy to see you've done something wrong if you omit the condition accidentally.
Within a [=conditional rule chain=],
the conditions of each [=conditional group rule=] are evaluated in order.
If one of them is true,
the conditions of all <em>following</em> [=conditional group rules=] in the chain
evaluate to false,
regardless of their stated condition.
An ''@else'' rule that is not part of a [=conditional rule chain=]
is invalid and must be ignored.
<div class=example>
For example, here's a (somewhat silly) conditional chain:
<pre class="lang-css">
@when media(width >= 400px) and media(pointer: fine) and supports(display: flex) {
/* A */
} @else supports(caret-color: pink) and supports(background: double-rainbow()) {
/* B */
} @else {
/* C */
}
</pre>
Exactly one of the preceding rules will be chosen,
even though the second rule
doesn't exclude large widths, fine points, or flexbox support,
and the last rule
doesn't specify anything at all.
To achieve the same result without [=conditional rule chains=],
you'd need to write:
<pre class="lang-css">
@media (width >= 400px) and (pointer: fine) {
@supports (display: flex) {
/* A */
}
@supports not (display: flex) {
@supports (caret-color: pink) and (background: double-rainbow()) {
/* B */
}
@supports not ((caret-color: pink) and (background: double-rainbow())) {
/* C */
}
}
}
@media not ((width >= 400px) and (pointer: fine)) {
@supports (caret-color: pink) and (background: double-rainbow()) {
/* B */
}
@supports not ((caret-color: pink) and (background: double-rainbow())) {
/* C */
}
}
</pre>
This is simultaneously hard to read,
requires significant duplication of both conditions and contents,
and is <em>very</em> difficult to write correctly.
<!-- (I wrote it wrong <em>twice</em> while producing this example.) -->
If the conditions got any more complicated
(which is not unusual in real-world content),
the example would get <em>significantly</em> worse.
</div>
<div class="example">
In this example, three different color font technologies
are tested, in order of preference,
plus a monochrome fallback.
The most capable, COLRv1, supports both gradients and font variations;
the next best choice, SVG, supports gradients
while the least capable, COLRv0, supports flat color fill only.
The fallback has no test condition,
so will always be chosen unless one of the earlier conditions succeeds.
<pre class="lang-css">
@when font-tech(color-COLRv1) and font-tech(variations) {
@font-face { font-family: icons; src: url(icons-gradient-var.woff2); }
}
@else font-tech(color-SVG) {
@font-face { font-family: icons; src: url(icons-gradient.woff2); }
}
@else font-tech(color-COLRv0) {
@font-face { font-family: icons; src: url(icons-flat.woff2); }
}
@else {
@font-face { font-family: icons; src: url(icons-fallback.woff2); }
}
</pre>
Notice that in this example,
the variable color font is only downloaded
if COLRv1 is supported
and font variations are also supported.
Notice too that only one of the available options will be downloaded;
this would not be the case without ''@when'' and ''@else'',
as the next example shows.
</div>
<div class="example">
In this example,
although it appears that the fallback will not be used
if COLRv1 is supported,
in fact both fonts will be downloaded,
which wastes bandwidth if it is not used.
The fallback might still be used for some characters;
for example, if the color font supports only Latin,
while the fallback supports Latin and Greek.
<pre class="lang-css">
@font-face { font-family: icons; src: url(icons-fallback.woff2);
@supports font-tech(color-COLRv1) {
@font-face { font-family: icons; src: url(icons-gradient-var.woff2); }
}
</pre>
</div>
<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 <dfn export lt="query container">query containers</dfn>
for the purpose of [=container style queries=],
and can be established as [=query containers=]
for [=container size queries=] and [=container scroll-state queries=] by specifying
the additional query types using the 'container-type' property
(or the 'container' [=shorthand=]).
Style rules applying to a [=query container=]’s [=flat tree=] descendants
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 the ''::part()'' and ''::slotted()'' <a>pseudo-element</a> selectors,
which represent real elements in the DOM tree, [=query containers=] can be
established by [=flat tree=] ancestors of those elements.
For other <a>pseudo-element</a>s, [=query containers=] can be established by
inclusive [=flat tree=] ancestors of their <a>originating element</a>.
<div class=note>
It follows that:
* ''::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
* ''::slotted()'' selectors can query containers inside the shadow tree,
including the slot itself
* ''::slotted()::before'' selectors can query the slotted shadow host child
* ''::part()'' selectors can 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 ] || scroll-state ]
Initial: normal
Inherited: no
Applies to: all elements
Computed value: specified keyword
Animation type: not animatable
</pre>
The 'container-type' property establishes the element as a
[=query container=] for certain types of queries. For size
[=container queries=], which require certain types of containment, elements
are explicitly made [=query containers=] through this property. For other
types of [=query containers=] any element can be a [=query container=], such
as for [=container style queries=].
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>scroll-state</dfn>
<dd>
Establishes a [=query container=] for [=scroll-state queries=]
<dt><dfn>normal</dfn>
<dd>
The element is not a [=query container=]
for any [=container size queries=] or [=scroll-state 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>
@container style(--cards: small) {
article {
border: thin solid silver;
border-radius: 0.5em;
padding: 1em;
}
}
</pre>
</div>
<div class=example>
Containers can also expose state that depends on scroll offset. This example
styles a descendant of a sticky positioned element when it is stuck to the
top edge:
<pre class=lang-css>
#sticky {
container-type: scroll-state;
position: sticky;
}
@container scroll-state(stuck: top) {
#sticky-child {
background-color: lime;
}
}
</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 <<block-contents>> 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>># {
<<block-contents>>
}
</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>> )
| scroll-state( <<scroll-state-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>>
<dfn><<scroll-state-query>></dfn> = not <<scroll-state-in-parens>>
| <<scroll-state-in-parens>> [ [ and <<scroll-state-in-parens>> ]* | [ or <<scroll-state-in-parens>> ]* ]
| <<scroll-state-feature>>
<dfn><<scroll-state-in-parens>></dfn> = ( <<scroll-state-query>> )
| ( <<scroll-state-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>>. If the <<container-query>> contains
unknown or unsupported [=container feature=]s,
no [=query container=] will be selected for that <<container-condition>>.
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.
As with media queries, <<general-enclosed>> evaluates to ''unknown''.
If a [=container query=] includes multiple <<container-condition>>s,
each condition will select it's own [=query container=],
and evaluate independently.
A [=container query=] is ''true'' if <em>any</em> of its component
<<container-condition>>s are ''true'',
and ''false'' only if <em>all</em> of its component
<<container-condition>>s are ''false''.
<div class=example>
As with [=media queries=],
we can string together multiple queries in a single condition:
<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.
We can also combine multiple conditions into a list,
with each condition evaluating against a different container:
<pre class=lang-css>
@container card (inline-size > 30em), style(--large: true) {
/* styles */
}
</pre>
The styles above will be applied
if there is an ancestor container named "card"
that meets the '@container/inline-size' condition
<em>or</em> the nearest style container
meets the [=container style query|style=] condition.
</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>
Using a single comma-separated [=container query=],
we can query multiple containers:
<pre class=lang-css>
@container card (inline-size > 30em), style(--responsive: true) {
/* styles */
}
</pre>
The styles above will apply for an element inside <em>either</em>
a container named "card" that meets the '@container/inline-size' condition,
<em>or</em> a container meeting the [=container style query|style=] condition.
In order to require that <em>all</em> conditions are met
while querying multiple containers,
we would need to nest 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 <em>both</em> an ancestor container named "card"
that meets the '@container/inline-size' condition,
<em>and</em> an ancestor container
meeting the [=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)
and [=custom properties=]
in [=container query=] conditions
are evaluated based on the [=computed values=] of the [=query container=].
Note: This is different from the handling of relative units in [=media queries=].
Note: If [=custom property=] substitution results in an invalid value for the
[=size feature=], it is handled the same as other invalid feature values,
and the result of the [=size feature=] is ''unknown''.
<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>
<div class=example>
Similarly, [=query containers=] will evaluate ''var()''-based queries
relative to their own [=computed value=] of the [=custom property=]:
<pre class=lang-css>
aside, main {
container-type: inline-size;
}
aside { --query: 300px; }
main { --query: 500px; }
@container (width > var(--query)) {
h2 { font-size: 1.5em; }
}
</pre>
The ''var(--query)'' value used in the query condition
is substituted with the [=computed value=] of
the ''--query'' [=custom property=] on the relevant [=query container=]:
* For any ''h2'' inside ''aside'',
the query condition will be true above ''300px''.
* For any ''h2'' inside ''main'',
the query condition will be true above ''500px''.
</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=].