A good[ish] website
Web development blog, loads of UI and JavaScript topics
There’s a new CSS property in town called content-visibility
. It will defer the rendering of elements until they’re about to hit the viewport. Calling it "lazy rendering" might be a helpful analogy.
Here’s a demo of a simple landing page with cat pictures:
There’s not much to see, the difference is more under the hood.
Although browsers are generally fast at rendering HTML (it’s their 9-to-5 job), but they still break a sweat for it, specifically when working on modern sites packed full of visually esoteric bells and whistles.
But why do you need to render a module at the bottom of the page, when you’re at the top? Because the browser needs to know all the elements on the page before it can start the paint, there can be an element in the footer that is absolutely positioned to be at the top of the page, for example. The browser needs to see the full page to be able to render anything.
But not anymore, kind of.
We’re all, more-or-less, familiar with image lazy loading, right? content-visibility
is similar, but for CSS rendering. Now we can tell the browser to defer the rendering work of certain segments of the page—like layout-heavy landing page modules—and only render them when they are about to be visible. Without breaking in-page search or SEO.
Sounds too good to be true? You’re right, it is too good to be true, . The accessibility issues have been fixed in Chrome 90!content-visibility
has some accessibility issues (see the accessibility issues segment below)
Only two CSS rules are needed:
.module {
content-visibility: auto;
contain-intrinsic-size: 0 500px;
}
contain-intrinsic-size
is needed because the component looses it’s height in the layout, because the browser needs to render the component before it knows that. The 500px
is just an estimation.
Note that contain-intrinsic-size
doesn’t define the elements size, but size of the content size.
Here are all the values you can feed it:
display: none
, but not completely. This post "Short note on content-visibility: hidden" by stevef, goes deeper into the topic.Like many new programming related things, content-visibility comes with its limitations and bugs.
If you scroll the above demo you’ll see that the scrollbar appears rather jagged, that’s the page content adjusting itself to the new content being rendered. The more accurately you match the intrinsic-size
to the element’s actual height, the less jerky it is. But that’s impossible to do accurately because often on fluid sites the content height is dependent on the screen width.
I really don’t mind that, though. I’ll take faster load time over such a small aesthetic imperfection. Though, it’s good to keep in mind, that a clean looking website conveys trust and might translate to a higher conversion rate. But I think content-visibility
makes the cut in that sense.
It seems like the accessibility issues have been solved in Chrome 90. The web.dev article has been updated.
Specifically with headings:
Neat. But my spidey accessibility senses went off as soon as I read those words: off-screen and rendering. [...] My initial thought was that
content-visibility: auto
could pose an access problem on initial load by suppressing part of the page outline from screen readers, so I set out to test it. Marcy Sutton
According to that article 👆 (great read), headings inside the components of which render work has been deferred, are not visible to a some screen readers, NVDA to be specific. This means that user needs to scroll through the page for the headings to be read.
Which is not good, and which makes this kind of useless, at least for now. Based on this Tweet it seems like a bug and will be fixed at some point 🤞
So, use content-visibility
only on elements that have no headings or landmarks in them. Like a footer, or a long list of cards-like UI elements, or long image-heavy lists.
It also seems that content-visibility
can break in-page navigation.
This will be an amazing feature when the accessibility issues have been solved. It's fixed and I guess it’s now an amazing!
Also a cool side effect is a smoother screen resizing experience, because there’s less layout for the browser to calculate.
I’m not 100% sure, but content-visibility
might solve the ages old issues of infinitely scrolling list; list gets big, scrolling becomes janky. That’s why we have packages like react-window.
Thanks for reading. Hope this was helpful.
Comments would go here, but the commenting system isn’t ready yet, sorry.