Monday, February 19th, 2024
It worked. But I also wrote:
Take a tune like Out On The Ocean. It has 27 settings. That’s a lot of SVG markup that needs to be parsed, styled and rendered, even if it’s inline.
Then I remembered a very handy CSS property called
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.
Sounds great! But there are two gotchas.
The first gotcha is that if a browser doesn’t paint the element, it doesn’t know how much space the element should take up. So you need to provide dimensions. At the very least you need to provide a height value. Otherwise when the element comes into view and gets rendered, it pushes down on the content below it. You’d see a sudden jump in the scrollbar position.
The solution is to provide a value for
contain-intrinsic-size. If your content is dynamic—from, say, a CMS—then you’re out of luck. You don’t know how long the content is.
Luckily, in my case, I could take a stab at it. I know how many lines of sheetmusic there are for each tune setting. Each line takes up roughly the same amount of space. If I multiply that amount of space by the number of lines then I’ve got a pretty good approximation of the height of the sheetmusic. I apply this with the
So each piece of sheetmusic has an inline
style attribute with declarations like this:
It works a treat. I did a before-and-after check with pagespeed insights on the page for Out On The Ocean. The “style and layout” part of the main thread work went down considerably. Total blocking time went from more than 600 milliseconds to less than 400 milliseconds.
Not a bad result for a little bit of CSS!
I said there was a second gotcha. That’s browser support.
content-visibility is only supported in Chrome and Edge. But that’s okay. This is a progressive enhancement. Adding this CSS has no detrimental effect on the browsers that don’t understand it (and when they do ship support for it, it’ll just start working). I’ve said it before and I’ll say it again: the forgiving error-parsing in HTML and CSS is a killer feature of the web. Browsers just ignore what they don’t understand. That’s what makes progressive enhancement like this possible.
And actually, there’s something you can do for all browsers. Even browsers that don’t support
content-visibility still understand containment. So they’ll understand
contain-intrinsic-size. Pair that with a
contain declaration like this to tell the browser that this chunk of content isn’t going to reflow or get repainted:
contain: layout paint;
Here’s what MDN says about
containCSS property indicates that an element and its contents are, as much as possible, independent from the rest of the document tree. Containment enables isolating a subsection of the DOM, providing performance benefits by limiting calculations of layout, style, paint, size, or any combination to a DOM subtree rather than the entire page.
So if you’ve got a chunk of static content, you might as well apply
contain to it.
Again, not bad for a little bit of CSS!