Skip to content

Commit fe34647

Browse files
committed
[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.
1 parent 7fd843a commit fe34647

File tree

1 file changed

+165
-19
lines changed

1 file changed

+165
-19
lines changed

css-contain-2/Overview.bs

+165-19
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Previous Version: https://www.w3.org/TR/2019/WD-css-contain-2-20191015/
1010
TR: https://www.w3.org/TR/css-contain-2/
1111
Editor: Tab Atkins, Google, http://xanthir.com/contact/, w3cid 42199
1212
Editor: Florian Rivoal, On behalf of Bloomberg, https://florian.rivoal.net/, w3cid 43241
13+
Editor: Vladimir Levin, Google, vmpstr@google.com, w3cid 75295
1314
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.
1415
Test Suite: https://test.csswg.org/harness/results/css-contain-1_dev/
1516
WPT Path Prefix: css/css-contain/
@@ -678,7 +679,7 @@ Layout Containment</h3>
678679
contain-layout-ink-overflow-020.html
679680
</wpt>
680681

681-
4. The [=layout-containment/containing box=] establishes an [=absolute positioning containing block=] and a [=fixed positioning containing block=].
682+
4. The [=layout containment/containing box=] establishes an [=absolute positioning containing block=] and a [=fixed positioning containing block=].
682683

683684
<wpt>
684685
contain-layout-006.html
@@ -905,7 +906,7 @@ Paint Containment</h3>
905906
contain-paint-table-001.html
906907
contain-paint-table-002.html
907908
</wpt>
908-
2. The [=paint-containment/containing box=] establishes an [=absolute positioning containing block=] and a [=fixed positioning containing block=].
909+
2. The [=paint containment/containing box=] establishes an [=absolute positioning containing block=] and a [=fixed positioning containing block=].
909910

910911
<wpt>
911912
contain-paint-009.html
@@ -1013,12 +1014,12 @@ Suppressing An Element's Contents Entirely: the 'content-visibility' property {#
10131014
(the [=flat tree=] descendants of the element,
10141015
including both text and elements,
10151016
or the replaced content of a [=replaced element=])
1016-
are not rendered
1017+
are not painted
10171018
(as if they had ''visibility: hidden'')
10181019
and do not respond to hit-testing
10191020
(as if they had ''pointer-events: none'').
10201021

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
10221023
for [=skipped contents=];
10231024
the combination of heavy [=containment=]
10241025
and making the contents invisible and untouchable
@@ -1050,7 +1051,10 @@ Suppressing An Element's Contents Entirely: the 'content-visibility' property {#
10501051
since the results of such layouts
10511052
will not affect the container element’s size.
10521053

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.
10541058
</div>
10551059
</div>
10561060

@@ -1244,7 +1248,7 @@ Restrictions and Clarifications {#cv-notes}
12441248

12451249
1. From the perspective of an {{IntersectionObserver}},
12461250
the [=skipped contents=] of an element
1247-
are never intersecting the {{IntersectionObserver/root}}.
1251+
are never intersecting the [=intersection root=].
12481252
This is true even if both the root and the target elements
12491253
are in the [=skipped contents=].
12501254

@@ -1263,19 +1267,23 @@ Restrictions and Clarifications {#cv-notes}
12631267
Specifically, such changes will take effect right after
12641268
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.
12651269

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>
12791287

12801288
4. For the purposes of scrolling operations,
12811289
such as {{Element/scrollIntoView()}},
@@ -1314,6 +1322,144 @@ Restrictions and Clarifications {#cv-notes}
13141322

13151323
7. [=Skipped contents=] do not contribute to the result of {{HTMLElement/innerText}}.
13161324

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.
1461+
</div>
1462+
13171463

13181464

13191465

0 commit comments

Comments
 (0)