DEV Community

Murtaza Nathani
Murtaza Nathani

Posted on • Updated on

Two lines of CSS that boosts 7x rendering performance!

I'll cut the crap out and jump directly to the two line of css that you need to add to improve your performance by approx 7x:

{
  content-visibility: auto;
  contain-intrinsic-size: 1px 5000px;
}
Enter fullscreen mode Exit fullscreen mode

Why do you need this?

Website's nowadays need to be optimal and performant, users on the web have very short attention span. According to Doherty threshold response time to be 400 milliseconds.

Now imagine a website like Facebook,Instagram etc.. taking more time then the threshold ? No one would be coming back to these sites again.


When would you use this?

Most common use cases for this is when you have huge list/grid of data that needs to render at the mount of the application.

Example: Static website like specs or documentation or travel blogs etc...

Would love hear in comments if you have any other use cases for it.


How does it work ?

The browser acts smart by skipping rendering work with the class you applied with content-visibility: auto.

Browser needs to know the layout of the DOM in order to render, those elements which are not in viewport are not rendered and infact have empty box with contain-intrinsic-size you provided.

To summarize all of the rendering is deferred until it reaches the viewport at which the browser renders the actual layout with the width, height and styles you provided.

P.S: the layout which are not outside of the viewport would have a height: 0, so when deferred layout comes to viewport it would stack on top of each other, so that's why contain-intrinsic-size is needed, However, no worries these are just a fallback values, browser will render the actual ones when it renders in viewport.

Hence one drawback of this is the scrollbars would be wacky and jump to places if the contain-intrinsic-size not given properly. :)


Browser Support

content-visibility relies on the the CSS Containment Spec. While content-visibility currently is supported on mostly chromium tech as at the date of writing.

However, content-visibility support is not bad for a good to have feature on high end systems, however with progressing web development it will soon be supported in all browsers too. Hopefully :)


Alternatives

There are alternatives to improve performance using JavaScript, such using List virtualization, but who wants to write 100's of line of js and maintain it when you could do it in 2 lines of css

Further reading; that you could do it in js:
react-window
react-virtualized


Excellent demo and explanation:


Further readings:

https://web.dev/content-visibility/#support
https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility

Regards,

Discussion (58)

Collapse
arnebab profile image
Arne Babenhauserheide

There is no support in Firefox,¹² and it is only marked as "worth prototyping", with some remarks calling early versions of the spec actively harmful, especially to accessibility technology.³

Both points together instantly squelched my enthusiasm.

¹: developer.mozilla.org/en-US/docs/W...
²: developer.mozilla.org/en-US/docs/W...
³: github.com/mozilla/standards-posit...

As long as that does not change, this is not viable to use and other methods to speed up the site are preferable.

Collapse
mnathani profile image
Murtaza Nathani Author

Yeah that's very unfortunate.. but i am optimistic.

However, what I like is it supports chrome mobile devices too, where we have most of the low end devices...

Collapse
arnebab profile image
Arne Babenhauserheide

Shouldn’t that also be the case for every of the well-supported optimization techniques?

It is tempting to have a two-lines-solve-my-problems tool, but as long as there is no native FF support, it’s just not there. A polyfill won’t do here, because it won’t provide the performance of native, and performance is the very reason why this looks interesting.

Thread Thread
mnathani profile image
Murtaza Nathani Author

It's really depends on your app and your users.. so if 80% of your app is used by chrome users then it's not a bad solution, considering you do not have resources to do proper optimization using JS.

Moreover, on the web we have a huge ecosystem and I think it's hard for browsers to coupe up with all these optimization...

In my view: it's a good to have feature, maybe FF or safari needs to do so many others required thing's that maybe this could not be there priority

Thread Thread
arnebab profile image
Arne Babenhauserheide • Edited on

If you don’t have the resources to do proper optimization (not with JS but by doing what’s fast, also in CSS and by keeping your DOM sane), then that’s a problem by itself. If 80% of your app is used by Chrome users and you enable this feature, then it won’t be long until 100% of your users are Chrome users, because you will break performance for FF and Safari — after all, you still won’t have the resources to do proper optimization if you don’t have it before using this — so those users will leave.

EDIT: You will break performance, because you will have to cram in features without proper optimization until you hit the 400ms limit again with the optimization. Those without the optimization will then have an unusable App.

FF devs plan to prototype this feature, but their concerns were not “something else is more important”, but “this is actively harmful”, so depending on the outcome of the prototype, this might never get cross-browser support, locking you firmly into Chrome if you depend on it to get good load performance.

Thread Thread
mnathani profile image
Murtaza Nathani Author • Edited on

I kinda agree on the optimization point of view...

There's always more than one ways to do it, although might require more effort but why not.. that's how optimization comes in...

However, I highly doubt about being harmful.. it's very harsh term to use..

I will read again the Mozilla specification link to understand..

Thanks for contribution

Thread Thread
arnebab profile image
Arne Babenhauserheide

If the outcome of the prototype in FF is “yes, implementing this version is possible without causing deep other problems”, your solution might allow realizing the huge speedup you saw across different browsers, so please don’t let the wording keep you from experimenting with what might come.

After all, that Mozillians decided to prototype at all means that the changes in specification since this was declared harmful might have solved enough problems.

Collapse
ninjin profile image
Jin

This solution requires that you first load all the invisible data, create components for it, form the DOM, and only then will the browser decide that for 99% of that DOM, you don't need to calculate the layout.

The best solution is not to form this huge DOM at all. And don't even load invisible data. I told how to achieve this here: https://github-com.translate.goog/nin-jin/slides/tree/master/virt?_x_tr_sl=ru&_x_tr_tl=en&_x_tr_hl=ru&_x_tr_pto=wapp

Collapse
mnathani profile image
Murtaza Nathani Author

Thanks for sharing you work @ninjin , it looks great...

It depends on the usecase , well if you dont want to load all the data, then can't we do pagination or infinite scrolling ? that are the built in optimization..

Collapse
ninjin profile image
Jin

Yes, of course, and there I was just talking about how to get the effect of lazy loading and rendering without making any effort to optimize at the application level.
See the huge example: nin-jin.github.io/habrcomment/#art...
And its source code: github.com/nin-jin/habrcomment
Pagination and endless scrolling can't work well here.

Thread Thread
mnathani profile image
Murtaza Nathani Author

wow it looks smooth. Great effort bro.. scrolling of the doc seems rendering only the viewport 👍

Collapse
blackstar1991 profile image
Andry Zirka

hi. I tried use your ficha in real project. Unfortunately, I got a problem in the Chrome browser. jsfiddle.net/huy2o5rf/ Can you please explane why style

.btn_menu__checkbox:checked+.block_navigation {
transform: translateX(0);
}
would not work with your ficha ?

Collapse
mnathani profile image
Murtaza Nathani Author

hii @blackstar1991 , i saw your fiddle, and the css that you have applied is global

this would have no effect in the optimization:

 * {
  content-visibility: auto;
  contain-intrinsic-size: 1px 5000px;
}
Enter fullscreen mode Exit fullscreen mode

as in my understanding it would render the whole page will render after checking the layout without any optimization.
In your case, if you apply the above css in your items class bl_nav__item, it could work.

P.S: this optimization is usefull if you have 1000's of record loaded at the same time and you dont want to render it all at once..

I hope i am able to understand your issue and this could be any help.

Collapse
blackstar1991 profile image
Andry Zirka

in my example, I wanted to show you that we got problem with hidden element on a page. jsfiddle.net/rd2b37t4/ A psevdo menu dosn't work. .btn_menu__checkbox:checked+.block_navigation dosen't work if using your ficha

Collapse
zhouzi profile image
Gabin Aureche

That's very interesting, hopefully support will get better. As a side note, as for virtualization libraries I would rather recommend tanstack/virtual or react-virtuoso.

Collapse
mnathani profile image
Murtaza Nathani Author

wow, nice @zhouzi ..

Thanks for sharing these are good alternative to js virtualization 👍

Collapse
bptarpley profile image
Bryan Tarpley

I had trouble getting this to work for my use case, which also involves lazy loading images inside the sections where I attempted to apply this CSS trick. The negative side-effect of lazy loading images inside a section with this CSS applied was that when I rapidly scrolled down the page to a given section, the image didn't always render correctly (weirdly pixelated or obscured) until I scrolled away and then back. In the end, what seems to work best for my particular scenario is relying entirely on the JS Intersection Observer API:

developer.mozilla.org/en-US/docs/W...

Collapse
mnathani profile image
Murtaza Nathani Author • Edited on

Ummm, interesting...

Just a thought do we need to lazy load image's if you already rendering only what's in viewport ?.. since we aren't rendering other than what's in viewport, so for me it looks like tradeoff..

Also maybe try playing with different contain-intrinsic-size, might help with obscureness. ?

Moreover, intersection observer is also a good option.. there's always more than one solution to do it.. whichever suit's the best.. )

Collapse
albertwiersch profile image
Albert Wiersch

"Now imagine a website like Facebook,Instagram etc.. taking more time then the threshold ? No one would be coming back to these sites again."

Facebook is slow, buggy, and bogged down but I keep coming back to it...

Collapse
mnathani profile image
Murtaza Nathani Author

Then you must watch a Netflix documentary: "The social dilemma"

netflix.com/my-en/title/81254224?p...

Collapse
thisiscetin profile image
M. Cetin

Hi, how did you measure 7x? Do you have any benchmarks?

Collapse
mnathani profile image
Murtaza Nathani Author

Hey.. I learned this stats from link attached in doc.. where it shows how a travel blog FCP changed from 232ms to 30ms.. which is 7x faster

web.dev/content-visibility/#example

Collapse
mnathani profile image
Murtaza Nathani Author

Moreover, you can also check the benchmarks using profiler/performance in chrome dev tools as well..

try running with and without it.. would be a cool learning :)

mnathani profile image
Murtaza Nathani Author

It depends on your usecase of where this feature is best used for...

Yes one side effects of this is the scrollbars position, but in my understanding it's not issue considering Infinite pages or huge static chunk that needs to render

Collapse
jrohatiner profile image
Judith

Question re: contain-intrinsic-size: how did you come up with the values you used? Is 1px 5000px the max the screen will allow? Thx in advance🙏🏼

Collapse
mnathani profile image
Murtaza Nathani Author • Edited on

Hii,

It's just a random value, you can put whatever value you want according to design..

In my understanding it has these effects:

  1. The bigger the size value the bigger the layout boxes will be created, which are outside of viewport.
  2. Bigger the layout box the more the scrollbar will jump.. since it will render the actual styles when in viewport, so the height of the page will change.
  3. Lastly in order to not make the scrollbar wacky, we can keep the size smaller or close to design value too...

Furthermore, I came up with this value when was watching the YouTube video I have attached, it's really a great explanation to understand the concept.

Collapse
jrohatiner profile image
Judith

Thx! That covers it 👍

Collapse
kissu profile image
Konstantin BIFERT

Wow, thanks for that one!

Collapse
mnathani profile image
Murtaza Nathani Author

Welcome

Collapse
jmau111 profile image
jmau111

Very cool.

Most common use cases for this is when you have huge list/grid of data that needs to render at the mount of the application.

Did you measure the impact ?

Collapse
marcojhb profile image
Marco Agas

Does apply for WordPress? I tried applying it to .content_wrap but it made the speed worse. Any ideas?

Collapse
mnathani profile image
Murtaza Nathani Author • Edited on

Umm.. shouldn't matter if it's WordPress or custom website boss.

It should optimized the same way as shown here..

Moreover, not sure where .content_wrap is used, plus hows the DOM structure..

Collapse
ryanguitar profile image
Ryan Els

Looks very interesting.
Will need to give it a try.
Thanks for sharing.

Collapse
mnathani profile image
Murtaza Nathani Author

thanks.

Collapse
elijahtrillionz profile image
Elijah Trillionz

Great article.
Looking forward to trying this

Collapse
mnathani profile image
Murtaza Nathani Author

Thanks 🙏

Collapse
yomassive profile image
Andrew Belykh

Nice. Thanks!

Collapse
mnathani profile image
Murtaza Nathani Author

Welcome

Collapse
brunoj profile image
Bruno

Awesome article.

Collapse
mnathani profile image
Murtaza Nathani Author

Thanks 🙏

Collapse
rzs401 profile image
Richard Smith

This is awesome

Collapse
mjcoder_5 profile image
MJCoder

Nice! I never knew about this, I'll have to give it a try when I my hectic schedule isn't too hectic!

Collapse
mnathani profile image
Murtaza Nathani Author

haha yea.. try with your on going work ;)

Collapse
maxfindel profile image
Max F. Findel

This sounds too good to be true 😂 I'm definitely gonna try it out. Thanks for sharing!

Collapse
mnathani profile image
Murtaza Nathani Author • Edited on

Haha.. the world is surely a better place to live in :p

Let us know what you find out after trying.. it's always good to share knowledge :)

Collapse
samyak_bumb profile image
Samyak Bumb

Where to add that line means body or unversal selector

Collapse
mnathani profile image
Murtaza Nathani Author

Not really sure what your usecase is... however for example if you have a list of items/elements, then try adding it on item..

One of the best way to test it using chrome dev tools.

Collapse
alieldeba profile image
Ali-Eldeba

Where to put these two lines ?
For example in the * or in the body ... etc

Collapse
mnathani profile image
Murtaza Nathani Author • Edited on

Consider it like you have a scrollable list, and few items are visible from the list, so in order to optimize, browser needs to know not to render rest of items.

So in this case the css will be added on each item of the list to work.

Collapse
jorgeaguirreleon profile image
Jorge

This looks very promising!

It makes me wonder... if you are a 10x developer and apply this boost...
Do you become a legendary 70x developer?

Collapse
mnathani profile image
Murtaza Nathani Author

Well in this case if you are 0x, and apply this boost... then no, still 0x 🤪😂

Collapse
mnathani profile image
Murtaza Nathani Author • Edited on

Let us know when you try it out.. would love to hear your findings

Collapse
jahirfiquitiva profile image
Jahir Fiquitiva

Is it just me or does the snippet miss a selector? 🤔 Great post, btw 🙌

Collapse
mnathani profile image
Murtaza Nathani Author

Thanks...

That's deliberate, so you can name the selector what you want ☺️

Collapse
javaarchive profile image
Raymond

Hmmm wonder what would happen if I set this as a global userstyle for a day, might introduce some noticable changes?

Collapse
mnathani profile image
Murtaza Nathani Author • Edited on

In my understanding the whole page will render without any optimization..

Infact it would add some extra checks before rendering to check in viewport or not ...

What do you think ? Have you tried check what happens ?