Using rel=preload for responsive images

If you’re looking to preload images in your webpages it’s probably because you’re trying to improve your Core Web Vitals scores, most specifically Largest Contentful Paint (LCP). Given these will be part of Google’s ranking algorithm in 2021 it’s vital to focus on improving these metrics.

Basic preload

Most websites will have at least one page which includes an image that’s the largest element in the viewport. This image will most certainly be responsible for your LCP score, and the bigger the image the more it’s likely to impact negatively on your score.

By using rel="preload" within the <head> of your webpage you can set the browser off downloading a file much sooner than if you waited for the rendering engine to request it when it arrives at that line of code, potentially after other render blocking resources.

Doing so is pretty simple…

<link rel="preload" as="image"  href="banner.jpg" />

Now your image will load sooner, and positively impact your LCP score.

Using responsive images

But what if you’re using responsive images? Preloading an image at the wrong size just isn’t going to do you any good. Consider we have the following image…

<img src="banner-sm.jpg" srcset="banner-sm.jpg 640w, banner-med.jpg 920w, banner-lg.jpg 1280w" sizes="50vw" alt="" />

Using only the href attribute as in the example above means you can only reference a single image, which might not be the same one the browser has deemed the right image to schow based on the screen size. This is where imagesrcset and imagesizes attributes come in handy:

<link rel="preload" as="image" href="banner-sm.jpg" imagesrcset="banner-sm.jpg 640w, banner-med.jpg 920w, banner-lg.jpg 1280w" imagesizes="50vw" />

Now the browser will select the appropriate image to download as it would for the <img> element. You even use it for pixel density rather than width too:

<link rel="preload" as="image" href="banner.jpg" imagesrcset="banner.jpg 1x, banner-2x.jpg 2x" />

What about the <picture> element

But how does this work for the <picture> element where you’re specifying different images based on a media query. For this we simple modify the original rel=”preload” reference. But first, here’s an example image…

<picture>
    <source src="banner-sm.jpg" media="(max-width: 640px)">
    <source src="banner-med.jpg" media="(max-width: 920px)">
    <img src="banner-lg.jpg">
</picture>

In this instance we need only add the media attribute and duplicate the reference for each image size.

<link rel="preload" as="image" href="banner-sm.jpg" media="(max-width: 640px)"/>
<link rel="preload" as="image" href="banner-med.jpg " media="(min-width: 641px) and (max-width: 920px)" as="image"/>
<link rel="preload" as="image" href=" banner-lg.jpg" media="(min-width: 921px)" />

The main difference between this and the media attributes within the image is that you need to specify both min and max widths for those in-between images. Unlike the <picture> element the browser isn’t going to load only a single image based on what best fits the current screen size. In the case of preload, the browser will load anything that meets the criteria set within the media attribute, even if that means loading images that won’t be output to the page.

You can also specify different file types

Though you can specify a type attribute for different file formats, like this:

<picture>
    <source src="banner.webp" type="image/webp" />
    <source src="banner.jpg" type="image/jpg" />
    <img src="banner.jpg">
</picture>

You may not want to do this in your preload link. You can use type="" in your preload, but any modern browser which supports both jpg and webp images is likely to download both images.

In this case it’s probably better to only preload the webp images as the support for webp and preload through different browsers is more closely aligned (see here and here).

Finding that more images are preloaded that expected?

When we first started using rel="preload" we noticed that Chrome had a habit of downloading two sizes of the image when we were using the media attribute.

As you might expect, we place our preload <link>’s high in the <head> so that the browser starts loading these resources as early as possible. But having them above everything else was the cause of the problem, as we’d demoted our meta viewport reference. Without this above our preloads the browser seemingly didn’t know which image was the right one to preload and so would sometimes download the wrong one as well as the right one later in the render path.

Understanding this, our code had to change so it resembled the following:

<meta name="viewport" content="width=device-width,initial-scale=1" />

<link rel="preload" as="image" href="banner-sm.jpg" media="(max-width: 640px)"/>
<link rel="preload" as="image" href="banner-med.jpg " media="(min-width: 641px) and (max-width: 920px)" as="image"/>
<link rel="preload" as="image" href=" banner-lg.jpg" media="(min-width: 90px)" />

Further Reading

While this article is focused on providing some info on using preload for responsive images, you can go a step further on servers that support HTTP/2 Push and instruct the server to send assets before the browser even starts to render the page.

So far, we’ve tended to use this more for stylesheets and fonts, but this can also be used for imagery. But without the ability to set attributes like media queries at this point, HTTP/2 Push might best reserved for images displayed at a single size; like your logo.


We'd love to hear from you!

If you think Bronco has the skills to take your business forward then what are you waiting for?

Get in Touch Today!

Discussion

Add a Comment