Boost page rendering performance using <content-visibility> web component

Brian Liu
4 min readJan 7, 2021
Image source from web.dev

August 2020, I came across Intersection Observer web API on a random tweet then checked out the MDN API document, I was so excited and wanting to integrate it to improve our page rendering performance. Luckily, there is a React Hook version of intersection observer already, react-intersection-observer, so it took no times for us to integrate. Since that time Intersection Observer is my favourite Web API 😍 whenever I need to toggle/animate/trigger components.

The same month, Google Dev Submit 2020 unveiled CSS content-visibility and contain-intrinsic-size properties which supports from Chrome 85. It’s shamed I was buried by developing project features and only came across during Xmas holiday. However, this is like the best Xmas surprise 🎁 for me and it takes my excitement to the next level, just two lines of CSS then I can achieve lazy loading, OMG I freaking love it. You can deep dive content-visibility on Google web.dev, a great article to explain how it works.

But, life is not always easy, content-visibility is still more like an experimental feature and not supporting the other two major browser Safari and Firefox. 😞

Browser compatibility table on MDN

Wait a minute… we have Intersection Observer javascript API and content-visibility CSS solution, why not combine these so we can provide a cross-browsers solution💡 Meanwhile, implement as a web component is the best choice coz it’s lightweight, high performance (shadow DOM) and great browsers compatibility. I spent 12 hours to digest web component and gave a birth of <content-visibility> v1 🎉

I chose lit-element base class to create this web component as it’s lightweight and great browser compatibility, especially their web component GitHub starter template is extremely handy makes the whole experience of creating web component zero-brainer.

Install content-visibility from NPM and start integrating with any JS frameworks (React, Vue, Preact, Angular, VanillaJS and etc).

npm i content-visibility --save

<content-visibility> web component compatibility

Alright, let’s see some results I tested on three major browsers, Chrome 87, Safari 14 and Firefox 84 and I used the exact same travel blog template (except I removed iframe ) that is used in web.dev Codepen

Rendering frames, Safari comes with an interesting tool, Rendering Frames Timeline, helps you to measure page rendering performance. I want to start with this result to demonstrate how it reduces unnecessary rendering.

97 rendering frames happened on the first view without integrating the <content-visibility> web component
only 49 rendering frames happened on the first view with <content-visibility>
More rendering frames happened when scrolling down

Time measurement, Chrome 87 uses CSS solution which completely handles by browser and you can see Rendering and Painting time are reduced around 50% and overall time reduced 1s .

Chrome 87 without/with <content-visibility>

Safari 14 fallbacks to use Intersection Observer API to detect if component appears on the viewport. Layout & Rendering time down from 15s to 8s and you can easily see not many rendering chunks happening after applied <content-visibility>

Safari 14 without <content-visibility>
Safari 14 with <content-visibility>

Firefox 84 also fallbacks to use Intersection Observer API.

Firefox 84 without <content-visibility>
Firefox 84 with <content-visibility>
Google PageSpeed test result before/after <content-visibility>

You probably wondering how many lines I changed for 👆 PageSpeed results, actually just 4 lines 👇

That’s it! Numbers are better than words to tell the story. I already integrated <content-visibility> web component with my production web application in Preact . This is just v1 and sure it can be extended and tweak from feedbacks. Give it a try and welcome to fork the source code and deep dive the implementation. I will find a time to write an article about the implementation but not urgent as logic is simple and straightforward.

--

--