Why preload responsive images

When a page requests an image that is far wider than the user's viewport, it wastes mobile data and slows down loading. Responsive images, defined with the srcset attribute and w descriptors, let the browser pick the optimum version for the current screen width:

<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w">

Standard <link rel="preload">, by contrast, addresses a single URL and cannot participate in that selection logic. It is designed for resources that are otherwise hard to discover early — fonts inside stylesheets, background images, or content loaded by scripts. Responsive image preloading extends this capability to images chosen via srcset. The browser can then identify the correct variant before it parses the <img> tag, which shortens the critical path significantly.

Using imagesrcset and imagesizes

The <link> element uses two dedicated attributes — imagesrcset and imagesizes — to support responsive image preloading. They use the same syntax as the srcset and sizes attributes on <img>. For an image declared as:

<img src="small.jpg" srcset="small.jpg 500w, large.jpg 2000w" sizes="50vw">

the matching preload in the document <head> is:

<link rel="preload" as="image" href="large.jpg" imagesrcset="small.jpg 500w, large.jpg 2000w" imagesizes="50vw">

This initiates a request using the exact resource selection logic that srcset and sizes apply, so the correct file is fetched without waiting for the image to be discovered in the markup.

Practical use cases

Dynamically injected images

Consider a slideshow that injects hero images through JavaScript. The first image cannot be found by the preload scanner, so the browser idles until the script runs and triggers the fetch. Declaring a preload for that first hero image moves the request earlier in the timeline, so the image is ready when rendering begins. The effect is visible in a network waterfall comparison: with preload, the image request starts almost immediately instead of waiting for script evaluation.

CSS background images with image-set

CSS lets you offer density-based variants with image-set:

background-image: image-set("cat.png" 1x, "cat-2x.png" 2x);

The catch is that the browser only discovers these resources after it downloads and parses all CSS in the <head>. You can move that moment forward by adding a preload in the markup:

<link rel="preload" as="image" imagesrcset="cat.png 1x, cat-2x.png 2x">

Note the deliberate omission of the href attribute. Browsers that support imagesrcset on <link> will fetch the appropriate variant early. Browsers that only understand the CSS image-set syntax will skip the preload and download the correct source when the stylesheet is processed — they simply miss the performance gain.

Measured impact

Preloading responsive images is theoretically sound, but does it pay off in practice? In a test using two builds of a demo PWA shop — one with preloaded hero images and one without — the results on a throttled connection were as follows (measured with WebPageTest):

  • Start Render stayed the same.
  • Speed Index improved by 273 ms, since images arrive faster but do not occupy a huge pixel area.
  • Last Painted Hero improved by 1.2 seconds, a substantial gain for perceived load.

The gains are strongest for websites that lazy load images with JavaScript and rely on images for their visual narrative. As with any preload, the technique matters most in initial viewport content.

The <picture> element gap and its workarounds

Preload does not yet support the full resolution algorithm of the <picture> element, which handles art direction. When the browser processes a <picture>, it walks the <source> elements' media attributes in order and selects the first match. Preload has no notion of ordering or first match, so you must translate the breakpoint logic yourself.

Given a <picture> that switches sources at 600px and 800px viewport widths, you would approximate the matching preloads as:

<link rel="preload" as="image" media="(max-width: 600px)" imagesrcset="image-1.jpg">
<link rel="preload" as="image" media="(max-width: 800px)" imagesrcset="image-2.jpg">

Using type for progressive enhancement

The <picture> element also lets you match on the first supported type attribute, so browsers can pick a modern format before falling back to a legacy one. Preload only offers partial support for this pattern: a browser downloads preloads only for the type values it can handle, which you can exploit to avoid downloading unsupported MIME types. However, unlike <picture>, the browser will not stop at the first supported type. If you include preloads for several formats, it will fetch all of them.

Avoid this pattern:

<link rel="preload" as="image" type="image/avif" imagesrcset="image.avif"><br>
<link rel="preload" as="image" type="image/webp" imagesrcset="image.webp"><br>
<link rel="preload" as="image" type="image/jpeg" imagesrcset="image.jpg">

Instead, preload only your most preferred format:

<link rel="preload" as="image" type="image/avif" imagesrcset="image.avif">

This acts as progressive enhancement: browsers that support AVIF benefit from the preload, and other browsers simply ignore it. For resources that are already quickly discoverable in the HTML, skip preload entirely and let the preload scanner pick up <picture> and <source> elements. This is a best practice, particularly when combined with Fetch Priority to prioritize the appropriate image, because it lets the browser preload the exact resource it supports and avoids stale preloads when markup changes.

Implications for LCP

Images can be Largest Contentful Paint (LCP) candidates, so preloading them can directly improve LCP scores. The technique provides the biggest benefit when the image is not present in the initial markup payload, which is why client-side rendered pages tend to see more improvement than server-rendered ones.