I’ve just started a refactor of some code for ChromeOS.dev and I’m starting with a tricky component that I’m looking to refactor into using container queries. This component has a
<picture> element in it that uses media queries for art direction. Works great now, but part of this refactor is going from 3 separate components that all basically do the same thing to one single, container query based one, so that media query needs to go. So I started digging in.
I found Sara Soueidan’s wonderful Component-level art direction with CSS Container Queries post which mentions this, but sadly doesn’t have an answer other than bumping the images to CSS. Ten I came across the
Thanks to wonderful work by Tim Kadlec, we’ve known since 2012 that
display: none images still get downloaded by browsers. This is because browsers try and eagerly download images before styling and layout has occurred to improve loading performance. But, something we didn’t have then, but we do have now, is built-in support for lazy loading via
loading="lazy" attribute on images.
I put together a quick CodePen proof of concept based on comments in the CSSWG issue and, sure enough,in Chrome anyway, a lazy loaded image won’t download if display is
none. And just like that, a solution emerged.
Now, the reason this isn’t great for performance is it will delay image loading, so largest contentful paint may suffer, so
<picture> elements are probably better most of the time. That said, if you need container based image art direction, here’s how you do it:
loading="lazy"to lazy load the desired images, one image per “art direction”
display: nonethe images that need to be art directed
- Use container queries to undo
Something to consider if you’re looking to give this a go in production:
- Small examples will probably seem to work fine, but do test if you’re using this a lot
- After talking this out with Una, she recommends adding a placeholder in to help prevent layout shift. You can probably accomplish something similar using a trick similar to what Sara mentions in her post; wrap your images in a parent with an
aspect-ratiothat can change based on what image is being pulled in (so more container queries)
That’s it! Go have fun with it!