You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[css-contain-2] Add in the a11y and examples sections. Clarify the observable behavior by saying "painting". Add Vlad as a co-editor, per WG resolution.
Editor: Florian Rivoal, On behalf of Bloomberg, https://florian.rivoal.net/, w3cid 43241
13
+
Editor: Vladimir Levin, Google, vmpstr@google.com, w3cid 75295
13
14
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.
14
15
Test Suite: https://test.csswg.org/harness/results/css-contain-1_dev/
15
16
WPT Path Prefix: css/css-contain/
@@ -678,7 +679,7 @@ Layout Containment</h3>
678
679
contain-layout-ink-overflow-020.html
679
680
</wpt>
680
681
681
-
4. The [=layout-containment/containing box=] establishes an [=absolute positioning containing block=] and a [=fixed positioning containing block=].
682
+
4. The [=layoutcontainment/containing box=] establishes an [=absolute positioning containing block=] and a [=fixed positioning containing block=].
682
683
683
684
<wpt>
684
685
contain-layout-006.html
@@ -905,7 +906,7 @@ Paint Containment</h3>
905
906
contain-paint-table-001.html
906
907
contain-paint-table-002.html
907
908
</wpt>
908
-
2. The [=paint-containment/containing box=] establishes an [=absolute positioning containing block=] and a [=fixed positioning containing block=].
909
+
2. The [=paintcontainment/containing box=] establishes an [=absolute positioning containing block=] and a [=fixed positioning containing block=].
909
910
910
911
<wpt>
911
912
contain-paint-009.html
@@ -1013,12 +1014,12 @@ Suppressing An Element's Contents Entirely: the 'content-visibility' property {#
1013
1014
(the [=flat tree=] descendants of the element,
1014
1015
including both text and elements,
1015
1016
or the replaced content of a [=replaced element=])
1016
-
are not rendered
1017
+
are not painted
1017
1018
(as if they had ''visibility: hidden'')
1018
1019
and do not respond to hit-testing
1019
1020
(as if they had ''pointer-events: none'').
1020
1021
1021
-
The user agent <em>should</em> avoid as much layout and rendering work as possible
1022
+
The user agent <em>should</em>additionally avoid as much layout/rendering work as possible
1022
1023
for [=skipped contents=];
1023
1024
the combination of heavy [=containment=]
1024
1025
and making the contents invisible and untouchable
@@ -1050,7 +1051,10 @@ Suppressing An Element's Contents Entirely: the 'content-visibility' property {#
1050
1051
since the results of such layouts
1051
1052
will not affect the container element’s size.
1052
1053
1053
-
Note that in the ''content-visibility: auto'' case, layout containment, style containment, and paint containment persist even if the element is not skipped. This is done to prevent layout changes that would be incurred by containment changes as a result element entering and exiting the skipped state.
1054
+
Note that in the ''content-visibility: auto'' case,
1055
+
[=layout containment=], [=style containment=], and [=paint containment=] persist even if the element is not [=skipped=].
1056
+
This is done to prevent layout changes that would be incurred by [=containment=] changes
1057
+
as a result of an element entering and exiting the [=skipped=] state.
1054
1058
</div>
1055
1059
</div>
1056
1060
@@ -1244,7 +1248,7 @@ Restrictions and Clarifications {#cv-notes}
1244
1248
1245
1249
1. From the perspective of an {{IntersectionObserver}},
1246
1250
the [=skipped contents=] of an element
1247
-
are never intersecting the {{IntersectionObserver/root}}.
1251
+
are never intersecting the [=intersection root=].
1248
1252
This is true even if both the root and the target elements
1249
1253
are in the [=skipped contents=].
1250
1254
@@ -1263,19 +1267,23 @@ Restrictions and Clarifications {#cv-notes}
1263
1267
Specifically, such changes will take effect right after
1264
1268
step 11 of <a href="https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering">Update the Rendering</a> step of the Processing Model.
1265
1269
1266
-
<div class=note>
1267
-
Determining the viewport intersection of the element can be done with an
1268
-
internal version of an IntersectionObserver. However, since the
1269
-
observations from this are dispatched at step 12 of Update the
1270
-
Rendering, any changes to the [=skipped=] (and thus painted) state will
1271
-
not be visible to the user until the next frame's processing. For this
1272
-
reason, updating the [=skipped=] state, including containment
1273
-
adjustments, is deferred to that frame as well. This ensures that script
1274
-
accessing, for example, the containment value of the element between
1275
-
these two events (internal intersection observation and [=skipped=] state
1276
-
update) will retrieve values consistent with current painted state and
1277
-
not cause any forced layouts.
1278
-
</div>
1270
+
<div class=note>
1271
+
Determining the viewport intersection of the element
1272
+
can be done with an internal version of an IntersectionObserver.
1273
+
However, since the observations from this are dispatched at
1274
+
step 12 of Update the Rendering,
1275
+
any changes to the [=skipped contents|skipped=] (and thus painted) state
1276
+
will not be visible to the user until the next frame's processing.
1277
+
For this reason, updating the [=skipped contents|skipped=] state,
1278
+
including containment adjustments,
1279
+
is deferred to that frame as well.
1280
+
This ensures that script accessing,
1281
+
for example,
1282
+
the containment value of the element between these two events
1283
+
(internal intersection observation and [=skipped contents|skipped=] state update)
1284
+
will retrieve values consistent with current painted state
1285
+
and not cause any forced layouts.
1286
+
</div>
1279
1287
1280
1288
4. For the purposes of scrolling operations,
1281
1289
such as {{Element/scrollIntoView()}},
@@ -1314,6 +1322,144 @@ Restrictions and Clarifications {#cv-notes}
1314
1322
1315
1323
7. [=Skipped contents=] do not contribute to the result of {{HTMLElement/innerText}}.
1316
1324
1325
+
Accessibility Implications {#cv-a11y}
1326
+
-------------------------------------
1327
+
1328
+
If a user agent exposes some form of "accessibility tree",
1329
+
akin to the DOM tree but specialized for accessibility use-cases such as screen-readers
1330
+
(thus providing the positions/etc of elements relevant to accessibility APIs,
1331
+
such as focusable elements),
1332
+
then the [=skipped contents=] of ''content-visibility: hidden'' elements
1333
+
must similarly be "skipped" (omitted) in the accessibility tree
1334
+
(similar to how ''display: none'' elements
1335
+
are omitted in all views of the document).
1336
+
1337
+
[=Skipped contents=] of ''content-visibility: auto'' elements
1338
+
must not expose the fact that a user is interacting with the page via the accessibility tree,
1339
+
rather than via rendering visually to the screen.
1340
+
In particular, if a user agent uses ''content-visibility: auto''
1341
+
to avoid doing layout and painting work on off-screen content
1342
+
for displaying to the screen,
1343
+
it must similarly avoid doing that work on off-screen content
1344
+
for representing in the accessibility tree.
1345
+
If this is not possible
1346
+
(for example, if the user agent's representation of a focusable element in the accessibility tree
1347
+
requires knowledge of its exact position,
1348
+
and thus requires a full layout to be done on it and surrounding contents),
1349
+
then the user agent <em>must</em> omit the [=skipped contents=] from the accessibility tree entirely.
1350
+
1351
+
Note: This requirement is intended to protect users utilizing accessibility tooling
1352
+
from being identified and profiled as such
1353
+
via observation of timing channels;
1354
+
if a user agent can skip significant amounts of work
1355
+
when rendering visually,
1356
+
but has to do all of the work when rendering to an accessibility tree,
1357
+
then an author can tell how a user is interacting with the page
1358
+
by observing the timing of layout operations.
1359
+
1360
+
Examples {#cv-examples}
1361
+
-----------------------
1362
+
1363
+
<div class=example>
1364
+
<xmp highlight=markup>
1365
+
<style>
1366
+
.sv {
1367
+
content-visibility: auto;
1368
+
min-height: 50px;
1369
+
}
1370
+
</style>
1371
+
1372
+
<div class=sv>
1373
+
... some content goes here ...
1374
+
</div>
1375
+
</xmp>
1376
+
1377
+
The .sv element's ''content-visibility: auto'' value
1378
+
lets the user-agent manage whether the element is [=skipped=].
1379
+
Specifically when this element is near the viewport,
1380
+
the user-agent will begin painting the element.
1381
+
When the element moves away from the viewport,
1382
+
it will stop being painted.
1383
+
In addition, the user-agent should skip as much of the rendering work as possible
1384
+
when the element is [=skipped=].
1385
+
</div>
1386
+
1387
+
<div class=example>
1388
+
<xmp highlight=markup>
1389
+
<style>
1390
+
.sv {
1391
+
content-visibility: hidden;
1392
+
}
1393
+
</style>
1394
+
1395
+
<div class=sv>
1396
+
... some content goes here ...
1397
+
</div>
1398
+
</xmp>
1399
+
1400
+
In this case, the element is [=skipped=] regardless of viewport intersection.
1401
+
This means that the only way to have the [=contents=] painted
1402
+
is via script updating the value to remove 'content-visibility' or change its value.
1403
+
As before, the user-agent should skip as much of the rendering in the [=contents=] as possible.
1404
+
1405
+
An additional effect of skipping rendering
1406
+
is that the layout state of the [=contents=] can be preserved by the user-agent,
1407
+
so that removing the 'content-visibility' property in the future
1408
+
will cause the [=contents=] to be rendered quicker
1409
+
than if they were hidden with ''display: none'' or similar.
1410
+
</div>
1411
+
1412
+
<div class=example>
1413
+
<xmp highlight=markup>
1414
+
<style>
1415
+
body {
1416
+
margin: 0;
1417
+
}
1418
+
.sv {
1419
+
content-visibility: hidden;
1420
+
position: relative;
1421
+
left: 10px;
1422
+
top: 20px;
1423
+
}
1424
+
#child {
1425
+
position: relative;
1426
+
left: 1px;
1427
+
top: 2px;
1428
+
width: 100px;
1429
+
height: 200px;
1430
+
}
1431
+
</style>
1432
+
1433
+
<div id=target class=sv>
1434
+
<div id=child></div>
1435
+
... some other content goes here ...
1436
+
</div>
1437
+
<script>
1438
+
...
1439
+
// This will force rendering work, including layout,
1440
+
// if the UA previously avoided it.
1441
+
target.firstElementChild.getBoundingClientRect();
1442
+
...
1443
+
</script>
1444
+
</xmp>
1445
+
1446
+
Similarly to the last example, the element is [=skipped=].
1447
+
The user-agent should avoid as much rendering work as possible.
1448
+
However, in this example, at some point script accesses a layout value in the element's [=contents=].
1449
+
In this situation, the user-agent cannot avoid rendering work
1450
+
and has to process any previously skipped rendering work
1451
+
in order to return a correct value to the caller.
1452
+
In this example, the result of {{Element/getBoundingClientRect()}}
1453
+
is a rect positioned at (11, 22) with a size 100x200.
1454
+
1455
+
Note that repeated calls to the same layout value
1456
+
should not cause any additional rendering work,
1457
+
since the user-agent should retain the last updated rendering state.
1458
+
1459
+
Also note that this situation in which rendering work is required is not unique.
1460
+
There may be other situations in which the user-agent cannot avoid rendering work.
0 commit comments