CSS Containment Module Level 3
Level: 3
Shortname: css-containment
Status: ED
Group: csswg
ED: http://dev.w3.org/csswg/css-containment/
Editor: Tab Atkins, Google, http://xanthir.com/contact/
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.
Ignored Terms: scrollWidth, scrollHeight, clientWidth, clientHeight, formatting context
Link Defaults: css-lists-3 (property) counter-increment, css-content-3 (property) string-set
Introduction
Efficiently rendering a website relies on the User Agent being able to detect what parts of the page are being displayed,
which parts might affect the currently-displayed section,
and what can be ignored.
There are various heuristics that can be used to guess when a given sub-tree is independent of the rest of the page in some manner,
but they're fragile,
so innocuous changes to a page may inadvertently make it flunk the heuristics and fall into a slow mode.
There are also many things that would be good to isolate which are difficult or impossible to detect in a heuristic manner.
To alleviate these problems
and allow strong, predictable isolation of a subtree from the rest of the page,
this specification defines a 'contain' property.
Strong Containment: the 'contain' property
Name: contain
Value: none | strict
Initial: none
Inherited: no
Applies to: all elements
Media: all
Computed value: specified value
The 'contain' property allows an author to indicate that an element and its contents are,
as much as possible,
independent of the rest of the document tree.
This allows user agents to utilize much stronger optimizations when rendering a page using 'contain' properly,
and allows authors to be confident that their page won't accidentally fall into a slow code path
due to an innocuous change.
- none
-
This value indicates that the property has no effect.
The element renders as normal,
with no containment effects applied.
- strict
-
The ''contain/strict'' value indicates that the element is strictly contained,
so that its contents are guaranteed to have no effect on the rest of the page outside the element's bounds.
Do we want to break this apart,
so people can opt into particular forms of containment without going whole-hog,
if they really need to?
'contain' is useful when used widely on a page,
particularly when a page contains a lot of "widgets" which are all independent.
For example, assume a micropost social network had markup something like this:
<body>
<aside class='sidebar'>...</aside>
<article class='messages'>
<section class='message'>
Lol, check out this dog: images.example.com/jsK3jkl
</section>
<section class='message'>
I had a ham sandwich today. #goodtimes
</section>
<section class='message'>
I have political opinions that you need to hear!
</section>
…
</article>
</body>
There are probably a
lot of messages displayed on the site,
but each is independent and won't affect anything else on the site.
As such, each can be marked with ''contain: strict'' to communicate this to the user agent,
so it can optimize the page and skip a lot of computation for messages that are off-screen.
An element that is strictly contained operates under the following restrictions:
-
The contents of the element must be clipped to the element's content box.
-
The element must not provide a scrolling user interface (such as a scrollbar),
nor be scrollable by any other means, such as dragging or script-based interaction.
-
The scrollWidth and scrollHeight attributes of the element's
DOM must return the same values as the clientWidth and clientHeight attributes, respectively.
Make sure this is the right way to define this. Also, ensure it's sane.
-
The element must act as a containing block for absolutely positioned and fixed positioned descendants.
-
The element must be a formatting context.
-
The following properties must have no effect on descendants of the element:
- 'break-*' (and the related aliases)
- 'bookmark-*'
- 'string-set'
-
The 'counter-increment', 'counter-set', 'flow-from', 'flow-into', and 'content' (for the purpose of ''open-quote''/etc values) properties must be scoped to the element's sub-tree.
A scoped property has its effects scoped to a particular element or subtree.
It must act as if the scoping element was the root of the document
for the purpose of evaluating the property's effects:
any uses of the property outside the scoping element must have no effect on the uses of the property on or in the scoping element,
and vice versa.
If scoped to a sub-tree, it's the same,
except the scoping element itself is counted as "outside" the tree,
like the rest of the document.
For example, if 'counter-increment' is scoped to an element,
the first use of it within the subtree acts as if the named counter were set to 0 at the scoping element,
regardless of whether the counter had been used outside the scoping element.
Any increments made within the subtree have no effect on counters of the same name outside the scoping element.