I haven’t heard about the contain property until some weeks ago when I asked about use cases for container queries on twitter and David Baron mentioned it in a response saying that contain: strict;
can avoid many of the theoretical problems of container queries. Since then I read the specification and everything I found about it trying to understand it; Here is what I learned.
The contain property
It’s a primitive for isolating style, layout, and paint. The contain property allows developers to limit a specific DOM sub-tree and the rest of the document; You can think of it like an iframe. Much like an iframe, this boundary establishes a new layout root, ensuring that DOM changes in the sub-tree never trigger reflows in the parent document.
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.
none | strict | layout | style | paint | size | contain
There are seven different values for the contain property.
- none no effect
- layout turns on layout containment
- style turns on style containment
- paint turns on paint containment
- size turns on size containment
- content all, except size containment
- strict layout, style and paint combined
Use cases
So far we know that by using CSS containment we can isolate elements from the rest of the document to mark them as independent parts. To show you where this can be helpful here are some use cases:
Widgets
When integrating third-party widgets you mostly don’t have much control and they can decrease the site performance dramatically by doing expensive layout, style or paint operations. To make them independent from our site we can set contain: strict;
for the most outer element of the third-party widget. This way, they won’t affect the performance of all the other parts of the page.
Off-Screen
If you build a off-screen navigation or similar, the browser paints the content completely although it is not visible on load. By setting contain: paint;
the user agent can skip the paint off the off-screen element and therefore paint all the other content faster.
Container queries
As I already mentioned in the beginning, contain: strict;
can avoid many of the problems of container queries. One of the “problems” of container queries is that the children and their content can have an effect on the size of the container. This can be avoided by using CSS containment.
Why can’t the browser do it automatically
Browser engines already make a lot of optimization under the hood when possible, but each engine has its differences. Using containment provides a standard way for applications to indicate to the user agent that it can optimize certain layout cases, which browser would otherwise not be able to optimize.
Bottom line
If you build simple sites without tons of DOM nodes and widgets you probably don’t have to care about CSS containment. On the other hand, if you build more complex sites CSS containment will help to optimize the performance. It is also a good idea to set contain: strict;
for third-party widgets to protect the performance of your site.
As always – test, test and test again. And not only test with fast network on a high-end machine, but test with old hardware and slow network. To get an idea how otheres experience your site you can also emulate the network speed and the CPU with Chrome Devtools.
Note: At the moment (April 2016) it is only supported in Chrome.
Update 06.04.2016: You need to turn on the flag chrome://flags/#enable-experimental-web-platform-features in Chrome at the moment to test CSS containment.
Update 20.05.2016: Now enabled by default in Chrome 52
Update 02.08.2016: Added the values “size” and “content” from the last update from the specification
Great stuff!
Do you think it will be useful for Ads as well? For example the expandable type.
I was thinking to add contain: strict; to the ad container.
Yes, I think it is a good idea to add contain:strict; to ads, same as for third-party widgets.
Very interesting! I wonder how browsers support this property. I can’t find it on caniuse 😐
As I mention in the bottom of the article, at the moment it is only available in Chrome (behind the flag chrome://flags/#enable-experimental-web-platform-features). If you want to see it on caniuse you can vote for it here: https://github.com/Fyrd/caniuse/issues/2410
What’s your understanding of the constraints for `contain: layout` (and, by extension, `contain: strict`)? From reading the definition of Layout Containment at https://drafts.csswg.org/css-containment-3/#containment-layout and especially the fourth point, my understanding is that the containing element must have fixed dimensions. E.g. `height:auto` would not be possible (unless the dimensions of the element are declared in another way like `top:0;bottom:0;`).
If that’s right, then the usefulness of `contain` will be limited to very few use cases, and it probably won’t help one bit for Container/Element queries.
Yes, from what I understand you should set a width&height (can be % or any other unit) to get all benefits of containment.