DEV Community

Sebastien Lorber
Sebastien Lorber

Posted on

CSS content-visibility for React devs

Hey, it's Seb from This Week In React here πŸ‘‹

For your information, with Safari 18 release, CSS content-visibility is now available in all browsers, and I think React developers should care.

Image description

I wanted to share the news in my newsletter, but the information is spread over Twitter, so I thought I'd aggregate the relevant bits here to make it more convenient to understand. It's not going to be a deep dive, I'm just sharing interesting references you might like.

Let's start with the MDN description:

It enables the user agent to skip an element's rendering work (including layout and painting) until it is needed β€” which makes the initial page load much faster.

TLDR: you can improve your page rendering performance (including Lighthouse score and SEO) with this new CSS rule, in particular with the content-visibility: auto; value on pages containing large lists.

It can be a good middle ground between bad rendering performance, and a React virtualization library, as long as you are able to approximately estimate the size of the list items.

.large-list-item {
  content-visibility: auto;
  contain-intrinsic-size: auto 500px;
}
Enter fullscreen mode Exit fullscreen mode

Malte Ubl (CTO of Vercel) also explained this on Twitter:

Image description

Image description

Vercel already uses it in production, giving some example use cases:

Image description

If you want a more concrete optimization case study, there's also this article from Nolan Lawson explaining how he optimized a slow emoji picker with content-visibility. Unfortunately, it doesn't seem to work immediately on <img loading="lazy"> tags.

Image description

Bonus: you improve the accessibility of your app compared to most virtualization solutions: you can ctrl+f and search for content that would otherwise not be in the DOM.

Even if it's not widely supported yet, it can be adopted today as a progressive enhancement.

See also this web.dev article.

Don't forget to subscribe to This Week In React for more news like this.

Top comments (3)

Collapse
 
raythurnevoid profile image
Ray Thurne Void • Edited

It has nothing to do with virtualization, virtualization in react is needed because react is incredibly slow at performing bulk operations on lists with over 100 items (eg update a checkbox on >100 items)

This is a JS world problem that can't be solved in CSS, the only way is to move away from React since every other solution perform well on this kind of tasks.

content-visibility on the other hand helps you on landing and maybe when scrolling the page on devices with little memory but it has the downside that scrolling causes contΓ­nuos Paint operations that overall translates in the CPU doing more work. You can check it yourself with the performance monitor tool on the devtools

Collapse
 
sebastienlorber profile image
Sebastien Lorber • Edited

It has nothing to do with virtualization

I don't know man, me, Vercel CTO and Nolan Lawson all think it has to with virtualization.

virtualization in react is needed because react is incredibly slow at performing bulk operations on lists with over 100 items (eg update a checkbox on >100 items)

Virtualization is needed for very long lists, even if these lists do not update.

The post from Nolan Lawson is not even using React and is displaying a long list of custom emojis that never update. There's no bulk operation here, and it's still useful to optimize the rendering of an emoji picker.

nolanlawson.com/2024/09/18/improvi...

This is a JS world problem that can't be solved in CSS, the only way is to move away from React since every other solution perform well on this kind of tasks.

You seem to dislike React and decided it was the main problem. I wonder how any other solution is better. React will soon have an edge on these solutions thanks to Concurrent React and the upcoming Offscreen / Activity feature that permits to render things not in the viewport in the background.

But for a list of 100 checkboxes, I doubt it's even useful to use it and React is fast enough if you don't use antipatterns to make it slow. And with the compiler it's also easier to optimize.

content-visibility on the other hand helps you on landing and maybe when scrolling the page on devices with little memory

Feelback from Vercel CTO actually using it in production in multiple places, and those places are not landing pages:

Image description

but it has the downside that scrolling causes contΓ­nuos Paint operations that overall translates in the CPU doing more work.

Is it better to use virtualization then? With virtualization you also paint on scroll in addition to executing JS.

I wonder what's your suggestion to keep both CPU/memory usage small on scroll?

Collapse
 
raythurnevoid profile image
Ray Thurne Void • Edited

You can't have both at the same time, depending on the situation you have to choose.

Assuming you are using Svelte/Vue/Solid/Vanilla

You can not do anything under 1000 rows if your content is made mostly by images/videos. You can imagine a long select/auto complete. (Low CPU, Normal Memory)

Over 1000 you may start to need virtualization depending on the average device of your user audience. (This means more CPU and more Memory, but better performance because you avoid overusing the Dom)

If you have many images/videos/gifs than you can make use content-visibility
(This will lover the memory but increase CPU)

If you want to lower memory your only option is to avoid it by using storage options and read only when you need something (indexedDB, Storage API, local storage)
(Lower memory, higher CPU, Higher disk usage)