@@ -348,10 +348,10 @@ Container Queries</h2>
348
348
[=container queries=] allow testing aspects of elements within the document
349
349
(such as box dimensions or computed styles).
350
350
351
- By default, all elements are [= query containers=]
351
+ By default, all elements are <dfn export lt=" query container">query containers</dfn>
352
352
for the purpose of [=container style queries=] ,
353
353
and can be established as [=query containers=]
354
- for [=container size queries=] by specifying
354
+ for [=container size queries=] and [=container scroll-state queries=] by specifying
355
355
the additional query types using the 'container-type' property
356
356
(or the 'container' [=shorthand=] ).
357
357
Style rules applying to a [=query container=] ’s [=flat tree=] descendants
@@ -385,9 +385,9 @@ Container Queries</h2>
385
385
</div>
386
386
387
387
For the ''::part()'' and ''::slotted()'' <a>pseudo-element</a> selectors,
388
- which represent real elements in the DOM tree, query containers can be
388
+ which represent real elements in the DOM tree, [= query containers=] can be
389
389
established by [=flat tree=] ancestors of those elements.
390
- For other <a>pseudo-element</a> s, query containers can be established by
390
+ For other <a>pseudo-element</a> s, [= query containers=] can be established by
391
391
inclusive [=flat tree=] ancestors of their <a>originating element</a> .
392
392
393
393
<div class=note>
@@ -461,28 +461,20 @@ Creating Query Containers: the 'container-type' property</h3>
461
461
462
462
<pre class='propdef'>
463
463
Name : container-type
464
- Value : normal | size | inline-size
464
+ Value : normal | [ [ size | inline-size ] || scroll-state ]
465
465
Initial : normal
466
466
Inherited : no
467
467
Applies to : all elements
468
468
Computed value : specified keyword
469
469
Animation type : not animatable
470
470
</pre>
471
471
472
- The 'container-type' property establishes the element
473
- as a <dfn export>query container</dfn>
474
- for the purpose of [=container queries=] that require explicit containment
475
- (such as [=container size queries=] ),
476
- allowing [=style rules=] styling its descendants
477
- to query various aspects of its sizing and layout,
478
- and respond accordingly.
479
-
480
- Unless otherwise noted,
481
- all elements are [=query containers=]
482
- for the purpose of [=container queries=]
483
- that do not require explicit [=containment=]
484
- (such as [=container style queries=] ),
485
- regardless of the specified 'container-type' .
472
+ The 'container-type' property establishes the element as a
473
+ [=query container=] for certain types of queries. For size
474
+ [=container queries=] , which require certain types of containment, elements
475
+ are explicitly made [=query containers=] through this property. For other
476
+ types of [=query containers=] any element can be a [=query container=] , such
477
+ as for [=container style queries=] .
486
478
487
479
Values have the following meanings:
488
480
@@ -503,10 +495,13 @@ Creating Query Containers: the 'container-type' property</h3>
503
495
[=style containment=] ,
504
496
and [=inline-size containment=]
505
497
to the [=principal box=] .
498
+ <dt> <dfn>scroll-state</dfn>
499
+ <dd>
500
+ Establishes a [=query container=] for [=scroll-state queries=]
506
501
<dt> <dfn>normal</dfn>
507
502
<dd>
508
503
The element is not a [=query container=]
509
- for any [=container size queries=] ,
504
+ for any [=container size queries=] or [=scroll-state queries=] ,
510
505
but remains a [=query container=] for [=container style queries=] .
511
506
</dl>
512
507
@@ -547,6 +542,23 @@ Creating Query Containers: the 'container-type' property</h3>
547
542
</pre>
548
543
</div>
549
544
545
+ <div class=example>
546
+ Containers can also expose state that depends on scroll offset. This example
547
+ styles a descendant of a sticky positioned element when it is stuck to the
548
+ top edge:
549
+
550
+ <pre class=lang-css>
551
+ #sticky {
552
+ container-type: scroll-state;
553
+ position: sticky;
554
+ }
555
+ @container scroll-state(stuck: top) {
556
+ #sticky-child {
557
+ background-color: lime;
558
+ }
559
+ }
560
+ </pre>
561
+ </div>
550
562
551
563
<h3 id="container-name">
552
564
Naming Query Containers: the 'container-name' property</h3>
@@ -658,19 +670,27 @@ Container Queries: the ''@container'' rule</h3>
658
670
<pre class="prod def">
659
671
<dfn><<container-condition>></dfn> = [ <<container-name>> ]? <<container-query>>
660
672
<dfn><<container-name>></dfn> = <<custom-ident>>
661
- <dfn><<container-query>></dfn> = not <<query-in-parens>>
662
- | <<query-in-parens>> [ [ and <<query-in-parens>> ]* | [ or <<query-in-parens>> ]* ]
663
- <dfn><<query-in-parens>></dfn> = ( <<container-query>> )
664
- | ( <<size-feature>> )
665
- | style( <<style-query>> )
666
- | <<general-enclosed>>
667
-
668
- <dfn><<style-query>></dfn> = not <<style-in-parens>>
669
- | <<style-in-parens>> [ [ and <<style-in-parens>> ]* | [ or <<style-in-parens>> ]* ]
670
- | <<style-feature>>
671
- <dfn><<style-in-parens>></dfn> = ( <<style-query>> )
672
- | ( <<style-feature>> )
673
- | <<general-enclosed>>
673
+ <dfn><<container-query>></dfn> = not <<query-in-parens>>
674
+ | <<query-in-parens>> [ [ and <<query-in-parens>> ]* | [ or <<query-in-parens>> ]* ]
675
+ <dfn><<query-in-parens>></dfn> = ( <<container-query>> )
676
+ | ( <<size-feature>> )
677
+ | style( <<style-query>> )
678
+ | scroll-state( <<scroll-state-query>> )
679
+ | <<general-enclosed>>
680
+
681
+ <dfn><<style-query>></dfn> = not <<style-in-parens>>
682
+ | <<style-in-parens>> [ [ and <<style-in-parens>> ]* | [ or <<style-in-parens>> ]* ]
683
+ | <<style-feature>>
684
+ <dfn><<style-in-parens>></dfn> = ( <<style-query>> )
685
+ | ( <<style-feature>> )
686
+ | <<general-enclosed>>
687
+
688
+ <dfn><<scroll-state-query>></dfn> = not <<scroll-state-in-parens>>
689
+ | <<scroll-state-in-parens>> [ [ and <<scroll-state-in-parens>> ]* | [ or <<scroll-state-in-parens>> ]* ]
690
+ | <<scroll-state-feature>>
691
+ <dfn><<scroll-state-in-parens>></dfn> = ( <<scroll-state-query>> )
692
+ | ( <<scroll-state-feature>> )
693
+ | <<general-enclosed>>
674
694
</pre>
675
695
676
696
The keywords ''container-name/none'' , ''and'' , ''not'' , and ''or''
@@ -1068,6 +1088,185 @@ Style Container Features</h3>
1068
1088
are [=computed value|computed=] with respect to the [=query container=] ,
1069
1089
the same as other values.
1070
1090
1091
+ <h3 id="scroll-state-container">
1092
+ Scroll State Container Features</h3>
1093
+
1094
+ A <dfn export>container scroll-state query</dfn> allows querying a container for
1095
+ state that depends on scroll position. It is a boolean combination of
1096
+ individual <dfn lt="scroll-state feature">scroll-state features</dfn>
1097
+ (<<scroll-state-feature>> ) that each query a single feature of the
1098
+ [=query container=] . The syntax of a <dfn><<scroll-state-feature>></dfn> is the
1099
+ same as for a [=media feature=] : a feature name, a comparator, and a value.
1100
+
1101
+ [=Scroll-state features=] can either match state of the scroller itself,
1102
+ or an element that is affected by the scroll position of an ancestor
1103
+ [=scroll container's=] [=scrollport=] . An example of the former is the
1104
+ ''overflowing'' feature, ''snapped'' the latter.
1105
+
1106
+ <h4 id="updating-scroll-state">
1107
+ Updating Scroll State</h4>
1108
+
1109
+ Issue(10796): This section is subject to change as a result of resolving
1110
+ the issue of unifying scroll-snapshotting layout state across several specifications.
1111
+
1112
+ Scroll state may cause layout cycles since queried scroll state may cause style changes,
1113
+ which may lead to scroll state changes as a result of layout. The same issue exists for
1114
+ [=scroll progress timelines=] , and scroll state is handled in a similar manner.
1115
+
1116
+ To avoid such layout cycles, ''scroll-state'' [=query containers=] update their
1117
+ current state once as the last step of [=run the scroll steps=] . Then, after the
1118
+ resizeObserver loop in the
1119
+ <a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model">HTML event loop processing model</a> ,
1120
+ update the current state of every ''scroll-state'' [=query container=] .
1121
+ If that state has changed since the scroll state update in [=run the scroll steps=] ,
1122
+ re-run the style and layout update a single time if necessary.
1123
+
1124
+ <h4 id="stuck">
1125
+ Sticky positioning: the '@container/stuck' feature</h4>
1126
+
1127
+ <pre class="descdef mq">
1128
+ Name : stuck
1129
+ For : @container
1130
+ Value : top | right | bottom | left | block-start | inline-start | block-end | inline-end
1131
+ Type : discrete
1132
+ </pre>
1133
+
1134
+ The '@container/stuck' [=container feature=] queries whether a
1135
+ ''position/sticky'' positioned container is visually shifted to stay inside
1136
+ the [=sticky view rectangle=] for the given edge. The logical edges map to
1137
+ physical based on the direction and writing-mode of the [=query container=] .
1138
+ None of the values match if the [=query container=] is not [=sticky positioned=] .
1139
+
1140
+ It is possible for two values from opposite axes to match at the same time,
1141
+ but not for opposite edges along the same axis.
1142
+
1143
+ <div class=example>
1144
+ May match:
1145
+ <pre class="lang-css">
1146
+ @container scroll-state((stuck: top) and (stuck: left)) { ... }
1147
+ </pre>
1148
+
1149
+ Will never match:
1150
+ <pre class="lang-css">
1151
+ @container scroll-state((stuck: left) and (stuck: right)) { ... }
1152
+ </pre>
1153
+ </div>
1154
+
1155
+ In the boolean context, the query matches if visual shift is applied in any
1156
+ direction.
1157
+
1158
+ <dl dfn-type=value dfn-for="@container/stuck">
1159
+ <dt> <dfn>top</dfn>
1160
+ <dd>
1161
+ The ''position/sticky'' container is shifted to stay inside the top edge.
1162
+ <dt> <dfn>right</dfn>
1163
+ <dd>
1164
+ The ''position/sticky'' container is shifted to stay inside the right edge.
1165
+ <dt> <dfn>bottom</dfn>
1166
+ <dd>
1167
+ The ''position/sticky'' container is shifted to stay inside the bottom edge.
1168
+ <dt> <dfn>left</dfn>
1169
+ <dd>
1170
+ The ''position/sticky'' container is shifted to stay inside the left edge.
1171
+ <dt> <dfn>block-start</dfn>
1172
+ <dd>
1173
+ The ''position/sticky'' container is shifted to stay inside the [=block-start=] edge.
1174
+ <dt> <dfn>inline-start</dfn>
1175
+ <dd>
1176
+ The ''position/sticky'' container is shifted to stay inside the [=inline-start=] edge.
1177
+ <dt> <dfn>block-end</dfn>
1178
+ <dd>
1179
+ The ''position/sticky'' container is shifted to stay inside the [=block-end=] edge.
1180
+ <dt> <dfn>inline-end</dfn>
1181
+ <dd>
1182
+ The ''position/sticky'' container is shifted to stay inside the [=inline-end=] edge.
1183
+ </dl>
1184
+
1185
+ <h4 id="snapped">
1186
+ Scroll snapping: the '@container/snapped' feature</h4>
1187
+
1188
+ <pre class="descdef mq">
1189
+ Name : snapped
1190
+ For : @container
1191
+ Value : x | y | block | inline
1192
+ Type : discrete
1193
+ </pre>
1194
+
1195
+ The '@container/snapped' [=container feature=] queries whether a [=snap target=]
1196
+ is snapped to its [=snap container=] in the given axis. It matches in the boolean
1197
+ context if it is snapped in at least one of the directions.
1198
+
1199
+ <dl dfn-type=value dfn-for="@container/snapped">
1200
+ <dt> <dfn>x</dfn>
1201
+ <dd>
1202
+ '@container/snapped' [=container feature=] matches ''x''
1203
+ if the [=query container=] is a horizontal [=snap target=] for its [=scroll container=]
1204
+ <dt> <dfn>y</dfn>
1205
+ <dd>
1206
+ '@container/snapped' [=container feature=] matches ''y''
1207
+ if the [=query container=] is a vertical [=snap target=] for its [=scroll container=]
1208
+ <dt> <dfn>block</dfn>
1209
+ <dd>
1210
+ '@container/snapped' [=container feature=] matches ''block''
1211
+ if the [=query container=] is a [=snap target=] for its [=scroll container=]
1212
+ in the block direction of the [=snap container=] .
1213
+ <dt> <dfn>inline</dfn>
1214
+ <dd>
1215
+ '@container/snapped' [=container feature=] matches ''inline''
1216
+ if the [=query container=] is a [=snap target=] for its [=scroll container=]
1217
+ in the inline direction of the [=snap container=] .
1218
+ </dl>
1219
+
1220
+ <h4 id="overflowing">
1221
+ Overflowing: the '@container/overflowing' feature</h4>
1222
+
1223
+ <pre class="descdef mq">
1224
+ Name : overflowing
1225
+ For : @container
1226
+ Value : top | right | bottom | left | block-start | inline-start | block-end | inline-end
1227
+ Type : discrete
1228
+ </pre>
1229
+
1230
+ The '@container/overflowing' [=container feature=] queries whether a
1231
+ [=scroll container=] has clipped [=scrollable overflow rectangle=] content
1232
+ in the given direction which is reachable through user initiated scrolling.
1233
+ That is, '@container/overflowing' does not match for a ''overflow/hidden''
1234
+ container, nor for a [=negative scrollable overflow region=] .
1235
+
1236
+ The logical values map to physical based on the direction and writing-mode of
1237
+ the [=query container=] . None of the values match if the container is not a
1238
+ [=scroll container=] .
1239
+
1240
+ In the boolean context, the query matches if any of the values match.
1241
+
1242
+ <dl dfn-type=value dfn-for="@container/overflowing">
1243
+ <dt> <dfn>top</dfn>
1244
+ <dd>
1245
+ The [=scroll container=] has [=scrollable overflow=] past the top edge.
1246
+ <dt> <dfn>right</dfn>
1247
+ <dd>
1248
+ The [=scroll container=] has [=scrollable overflow=] past the right edge.
1249
+ <dt> <dfn>bottom</dfn>
1250
+ <dd>
1251
+ The [=scroll container=] has [=scrollable overflow=] past the bottom edge.
1252
+ <dt> <dfn>left</dfn>
1253
+ <dd>
1254
+ The [=scroll container=] has [=scrollable overflow=] past the left edge.
1255
+ <dt> <dfn>block-start</dfn>
1256
+ <dd>
1257
+ The [=scroll container=] has [=scrollable overflow=] past the [=block-start=] edge.
1258
+ <dt> <dfn>inline-start</dfn>
1259
+ <dd>
1260
+ The [=scroll container=] has [=scrollable overflow=] past the [=inline-start=] edge.
1261
+ <dt> <dfn>block-end</dfn>
1262
+ <dd>
1263
+ The [=scroll container=] has [=scrollable overflow=] past the [=block-end=] edge.
1264
+ <dt> <dfn>inline-end</dfn>
1265
+ <dd>
1266
+ The [=scroll container=] has [=scrollable overflow=] past the [=inline-end=] edge.
1267
+ </dl>
1268
+
1269
+
1071
1270
<h2 id="container-lengths">
1072
1271
Container Relative Lengths: the ''cqw'', ''cqh'', ''cqi'', ''cqb'', ''cqmin'', ''cqmax'' units</h2>
1073
1272
0 commit comments