Preloading Images in a Responsive, WebP World
It’s time for another Google Core Web Vitals themed TIL. This one concerns image loading. Specifically, huge, above the fold image preloading.
The site I work on uses a lot of super wide to full width hero images. We’d done some previous optimizations around serving images in WebP format (Serve images in modern formats) and using picture
and srcset
for responsive images (Properly size images). I won’t go into details since those topics already have a ton of tutorials that explain things better than I ever could. In fact, Smashing Magazine alone has you covered with Using WebP Image Format Today and Responsive Images Done Right: A Guide To picture And srcset.
Preload critical assets to improve loading speed.
The one downside to our earlier work? It made things a little more confusing when we started looking into preloading images.
Preloading assets that aren’t actually used isn’t particularly helpful (Chrome will even warn you if you do it!). If you’re serving a WebP image but preloading the fallback or preloading a mobile image on a desktop browser, you aren’t getting any benefits out of it.
Let’s say you have a picture
block that selects an image based on browser support, screen resolution, and breakpoint:
<picture>
<source srcset="large-image.webp, large-image-2x.webp 2x" media="(min-width: 768px)" type="image/webp" />
<source srcset="large-image.jpg, large-image-2x.jpg 2x" media="(min-width: 768px)" />
<source srcset="small-image.webp, small-image-2x.webp 2x" type="image/webp" />
<img src="fallback-image.jpg" srcset="small-image.jpg, small-image-2x.jpg 2x" />
</picture>
The first question is how to handle different image formats. Looking at the Can I use entries for Webp image formats and preload, it seems pretty unlikely for a browser to support preloading but not WebP images. And according to a quick aside in this Addy Osmani article on hero images, you can use the type="image/webp"
attribute with a link
tag to specify that you want to preload a WebP image.
Next, we need to deal with screen sizes and resolutions. In addition to type
, the link
tag supports media
and imagesrcset
attributes which should look very similar to the media
and srcset
attributes on our source
and img
tags. The main difference is that you have to be more explicit with your breakpoints since the browser won’t be choosing the best image itself.
Putting that all together, you would add this code to your head
tag to preload the images from the example above:
<link rel="preload" as="image" href="large-image.webp" media="(min-width: 768px)" imagesrcset="large-image.webp, large-image-2x.webp 2x" type="image/webp" />
<link rel="preload" as="image" href="small-image.webp" media="(max-width: 767px)" imagesrcset="small-image.webp, small-image-2x.webp 2x" type="image/webp" />
If you prefer an example with real images, check out this Pen on Codepen. Just click on Settings and HTML to view the preloading the code.