loading...
Cover image for I made my website 28ms faster with content-visibility

I made my website 28ms faster with content-visibility

dailydevtips1 profile image Chris Bongers Originally published at daily-dev-tips.com 2 min read

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;
}

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

Posted on by:

dailydevtips1 profile

Chris Bongers

@dailydevtips1

I write daily web development tips that help you become a more efficient developer. 兩領∴

Discussion

pic
Editor guide
 

How do you handle the scrollbar?

 

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?

 

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

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)

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.

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. :(

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!

That seems really great!
Scrolls nice

What I noticed now, with lazy loading implemented on images the scroll bar also behave like that hence dont think is totally avoidable.

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!

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.

 

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 ?

 

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.

 

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

 

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...

 

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.

 

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

 

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...

 

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

 

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

 

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

 

Thanks dude! Adding content-vis-auto helper class to M- now...

 

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

 
Sloan, the sloth mascot Comment marked as low quality/non-constructive by the community View code of conduct

20/80. 20% of effort constitutes for 80% of the result. Rest 20% of the result require 80% of the effort. Though its just a saying, the general message is at some point efforts are not really worth it. IMO, all that time spent figuring out all the quirks and adjustments for such a small gain would bring more benefit if invested in a more proper direction. Efficiency.

 

I don't quite get your point about this article, to be honest?
It's a very easy to implement, low impact thing.
Are you saying we should not explore it because it's not a proper direction?