CSS Containment is already a powerful tool for improving web rendering performance. It lets developers tell the browser which parts of the DOM subtree are isolated from one another. The browser can then use that information to render content optimally.
For example, if the browser cannot determine on its own whether changes in one subtree would affect the appearance of another subtree, it has no choice but to re-render both. CSS Containment is a way of informing the browser that there is surely no need to re-render anything but the changed subtree itself. This effect may be minimal if there are few subtrees in question but can be significant in pages with highly complex DOM structures.
The new specification version gives developers even more control over how the browser uses the provided Containment information. Although the first public working draft of CSS Containment Module Level 2 was published nearly a year ago, its relevance to the average front-end developer will skyrocket now that Chrome 85 has moved from Beta to the Stable Channel. That is because Chrome 85 – released to the Stable Channel on August 25th,2020 – finally includes the new flagship feature of CSS Containment 2: the content-visibility property.
The content-visibility property provides new means of suppressing the rendering of an element’s contents to reduce load time and boost performance.
As the W3C specification describes, there are three possible values for the content-visibility property.
1. visible(default) – exhibits the same behavior that browsers currently have.
2. hidden– skips rendering the element’s contents entirely but retains the state of previously-computed layouts. Skipped contents are inaccessible to the user-agent.
3. auto– skips rendering the element’s contents if it is “not relevant” (i.e., not on-screen, focused, or selected) but retains the state of previously-computed layouts. Skipped contents are accessible to the user-agent.
All front-end developers should be very familiar with the ubiquitous display: none and visibility: hidden properties. At first glance, content-visibility:hidden appears similar enough: they are all ways of hiding content. Upon closer examination, however, you’ll find that content-visibility:hidden fills a niche nicely between these two options.
One downside of display:none is that – for elements that are shown and hidden regularly – the layout state is completely forgotten by the user-agent when the property is set. This means that the time it takes to re-render something once visible but then hidden is the same as the time it takes to render it in the first place.Elements hidden by the content-visibility property instead preserve their layout state, so the re-render can be performed much more quickly than the initial render.
A quirk of visibility:hidden mentioned by the CSS Containment 2 specification is that children of a hidden element can override the visibility property. This means that a container that is marked hidden is not guaranteed to be hidden in its entirety. Because nested elements need to be checked, not much is gained performance-wise by using this property. The content-visibility property does not have this issue, as its purpose is to inform the browser whether any rendering should be done at all. The children of an element hidden via its content-visibility are thus also guaranteed to be hidden.
The content-visibility:auto setting is, according to the specification, best understood as an upgrade to the existing features of CSS Containment. That is to say, it helps the browser to optimize rendering performance even more thoroughly than the use of the existing contain property alone.
We aim to stay on the cutting-edge of all technologies we work with and CSS is no exception. Considering that the majority of the front-end development we do is for Single Page Applications(SPAs), we see a lot of great use cases for content-visibility as the feature gains more widespread adoption by modern browsers.
As the CSS Containment 2 specification describes, SPAs in particular stand to benefit greatly from content-visibility:hidden. SPAs often feature elements that are not completely removed from the DOM and need to be hidden and shown again. With content-visibility: hidden, the layout states of hidden elements are retained so they can come back into the view smoothly, but not at the computational expense of keeping them styled and rendered even while off-screen.
For all elements that we currently hide with either of the other CSS properties, we should evaluate whether it makes sense to switch over to content-visibility.Furthermore, with this new tool at our disposal, we will need to rethink whether elements that are removed from the DOM entirely should be switched over to take advantage of content-visibility:hidden as well.
Although no other browsers but Chrome have announced plans to introduce this feature, it is likely that Firefox will follow suit, and movements have already begun to enter a prototype phase. Now that Edge runs on Chromium it should see the change as well. However, given that Safari has not implemented CSS Containment 1 in the several years since it was introduced, it is likely that Safari will continue to lag behind in this feature set.
Regardless, we will keep aiming for the absolute best user experience for all of our applications. Even though it may have to coexist with current solutions to ensure compatibility with legacy browsers for some time, we are confident that the latest in CSS Containment will play a big role in continuing to push the envelope on front end performance.
Want to take advantage of the latest Chrome update and pump up your web page’s performance on Chrome? Use content-visibility:hidden instead of display: none or visibility: hidden and use content-visibility: auto instead of contain: content.
About the author: Evan Ross is the Software Engineering Manager at S44. We achieve success by investing in our people and products with focus on innovation and solving complex business challenges.