DEV Community

Cover image for I made my website 28ms faster with content-visibility 🤓
Chris Bongers
Chris Bongers

Posted on • Originally published at daily-dev-tips.com

I made my website 28ms faster with content-visibility 🤓

You might think, what is 28ms? If you are a big advocate of speeding up the web and getting perfect scores on Eleventy's speedlify dashboard, it's a lot!

Not that I was doing bad, as you can see in the screenshot below. I just wanted to get full 100's and get the full potential out of my website.

Speedlify score Daily Dev Tips

Making use of content-visibility

I read about this CSS property a while ago. But never got round to implementing and testing it.
That is until today, so let's see what it actually does.

The content-visibility has three values we can use:

  • visible (no effect, basically how it was before)
  • hidden (a mix between display: none and visibility: hidden, it starts on display hidden, afterwords becomes visibility hidden)
  • auto (This is the one we are looking at. It will only render this element once the browser needs it!)

So how can we add it to elements?

.element {
    content-visibility:auto;
}
Enter fullscreen mode Exit fullscreen mode

I've added this on my homepage to the article-list and footer elements.

Before content-visibility

To give you a better understanding, I did a lighthouse test before these changes.

Before content-visibility

But more important is the actual trace where we can check the total time.

Lighthouse trace

After adding content-visibility

And then, after adding the content-visibility to those two elements, I've rerun the test.

Before content-visibility

And the trace:

Lighthouse trace

That means it was 443ms and is now 415ms, which means + 28ms win!

Conclusion: There is no downside to not adding the auto one. It can only benefit your website, even the small numbers matter.

Making sub-pages faster

I even added my content-visibility on the post pages, where the main content is set to auto.

The following screenshot is a before rendering:

Before content-visibility

And this is the after rendering:

After content-visibility

As you can see, it improved my score overall.
And adding content-visibility made the Time to Interactive 1.1s faster.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Top comments (37)

Collapse
 
marcellothearcane profile image
marcellothearcane

How do you handle the scrollbar?

Collapse
 
dailydevtips1 profile image
Chris Bongers

Not sure what you mean by that?
On the auto setting it handles the load on scroll for you, or am I misunderstanding your question?

Collapse
 
marcellothearcane profile image
marcellothearcane

Here's my website with content-visibility on: 5f6c55859d590d0007b1d834--tillys-w...

On the gallery page especially, watch scroll bar as you scroll up and down. It changes size and jumps about which is annoying

Thread Thread
 
dailydevtips1 profile image
Chris Bongers

I see! interesting!

You can add the following property, which should be helping with the scrollbar issue:

contain-intrinsic-size: 250px;

Have a play around with that 250px it's whatever it shows upfront.

More info:
stackoverflow.com/questions/636515...

Another option could be wrapping those multiple divs into 1 big one just for the content-visibility? (Not sure, but thinking out loud)

Thread Thread
 
marcellothearcane profile image
marcellothearcane • Edited

The problem is each div can have a wildly different height based on content and the browser width (because of responsive image layouts).

I've done it on the divs because a) they are 'slices' from my CMS so it was easy, and b) because if the top of the div is visible on page load, there's no benefit.

I'm messing around with ResizeObserver and can remove the content-visibility once the element is rendered which fixes the issue after the initial scroll-down:

// Vue
mounted () {
  const observer = new ResizeObserver(entries => {
    for (const entry of entries) {
      if (entry.target.getBoundingClientRect().height > 0) {
        observer.unobserve(entry.target)
        entry.target.classList.remove('content-visibility-auto')
      }
    }
  })

  for (const element of document.querySelectorAll('.content-visibility-auto')) {
    observer.observe(element)
  }
}

(yes I'll unobserve everything beforeDestroy, this is just testing 😄)

They aren't massive pages, so removing it isn't a problem after the initial load.

Thread Thread
 
dailydevtips1 profile image
Chris Bongers

Awesome, making use of what we have for now.
Unfortionally it's a not stable function yet. I had this issue where it hides half my divs on my detail pages. :(

Thread Thread
 
marcellothearcane profile image
marcellothearcane

This version's a bit more stable: 5f6c7268798c4d000721ae4b--tillys-w...

I used the ResizeObserver above to work out an average height value for the contain-intrinsic-size too.

A fun project, thanks for sharing this css trick!

Thread Thread
 
dailydevtips1 profile image
Chris Bongers

That seems really great!
Scrolls nice

Collapse
 
sandeshsapkota profile image
sandeshsapkota

Hi Chris, I am quite excited with this property and seems yet to be supported by many browsers. but quite confused with your screenshots. content-visibility property skips the rendering, layouting and painting of the elements which have a direct impact on rendering performance which we can see on the rendering on summary tab. in your screenshot it has increased by 1ms from 12ms to 13ms. what is happening ?

Collapse
 
dailydevtips1 profile image
Chris Bongers

Yes, not too sure how that works.
On paper, it should indeed cut down on that, but somehow it cuts down on other parts?

I don't quite know how it counts, but you are right it's very weird it doesn't make that less.

Collapse
 
sandeshsapkota profile image
sandeshsapkota

Yes. as this blog tells web.dev/content-visibility/ it has major impact on rendering.

 
marcellothearcane profile image
marcellothearcane • Edited

The images are meant to have height attributes, so it knows what size it is before it actually loads it. In theory.

There must be a point when too much JS outweighs the benefits that it is meant to add. Ah well, it's not too bad and it's faster than the old site!

Thread Thread
 
dailydevtips1 profile image
Chris Bongers

Yeah, it's always a mix of using too much JS for "simple" things and having a fast website.
Pretty hard to find a silver lining in there.

Collapse
 
tinny77 profile image
tinny77 • Edited

Remember to specify the height of the section you are going to hide with contain-intrinsic-size otherwise you will get jumps and scrollbar stange behaviours while scrolling your page. I needed a while to find out I missed the height property on my last project and that was the cause of the strange behaviour...

Collapse
 
dailydevtips1 profile image
Chris Bongers

Yes indeed check the comment above, marcello had the same issue. Did not see it before but indeed valid point 🥰

Collapse
 
axel186 profile image
Roman Axelrod

Very existed about the feature and waiting to play around with it since August...
It supported only from "Chrome v85".

I still suck with Chrome v84 :(
Maybe because I am using Linux...

Collapse
 
dailydevtips1 profile image
Chris Bongers

Ah that sucks, might be on delay indeed, mac is on 85 already.
But a very exciting feature, hopefully, it will become a mainstream one.

Collapse
 
axel186 profile image
Roman Axelrod

Anyway, very excited about your results and waiting patiently to the new version ;)
Thank you!

Collapse
 
madza profile image
Madza • Edited

Lighthouse looks so good on the dark theme 🔥
And agree on 28ms, its all the small things that count the most 💯

Collapse
 
dailydevtips1 profile image
Chris Bongers

100% I was reading this article that for every MS your slower you lose 7% of the people.

Collapse
 
pk2 profile image
pk2

You measure it wrong. content-visibility will cut rendering time not total and you have different idle time!

Collapse
 
dailydevtips1 profile image
Chris Bongers

Measuring the Total blocking time seems pretty reliable?
That's what it comes down to cutting on.

Collapse
 
pk2 profile image
pk2

Check this article
web.dev/content-visibility/
Idle can be +- few seconds.

Thread Thread
 
dailydevtips1 profile image
Chris Bongers

Yeah I've seen this one indeed
Still not sure, it will still show as total blocking time done in the test.

Collapse
 
winston0410 profile image
John Winston

Should we then just use content-visibility: auto for all elements, if it has no performance downside but benefits?

Collapse
 
dailydevtips1 profile image
Chris Bongers

Good question John,
It a thin line, so doing it will have no performance downside, but you might get issues with layout shifts.

I spend some more time on it, and if I use it on everything my layout shits are too much, so decided to only put it on certain elements, and try and define the height of the element.

Collapse
 
norbique profile image
norbique

I tried using this for the footer and unfortunately it makes my margins right and left, reduces the page layout, why?

Collapse
 
dailydevtips1 profile image
Chris Bongers

Hmm not sure, is your footer full width and the rest of your page not?
If that's the case it would be hidden on initial load so it won't work unless you specify the sizes.

Maybe you could setup a quick codepen, happy to take a look.

Collapse
 
aspiiire profile image
Aspiiire

What about old browsers support? :(

Collapse
 
dailydevtips1 profile image
Chris Bongers

What about it? haha
They don't contribute to your page speed scores, and they are not negatively affected by having this.

It will just be the same as not having it, but the point of having it is to speed up in modern browsers.

Old browsers are not fast by definition.

Collapse
 
mitchobrian profile image
Michael Palmer

What about add this to html,body in main css?!

Collapse
 
dailydevtips1 profile image
Chris Bongers

I don't think that will work, you'll end up with a flickering website and no profit since it will immediately fire is my assumption.

Collapse
 
dailydevtips1 profile image
Chris Bongers

Your welcome, that's an awesome idea actually!
Heading back to my code-cave

Some comments may only be visible to logged-in visitors. Sign in to view all comments.