This article gives me the opportunity to discuss two of my favorite things: responsive images. and preload. As someone who was very involved in the development of both features, I am so excited to see them work together!
Responsive Imaging Overview
Suppose you are browsing the web on a 300 pixel wide screen and the page requests a 1500 pixel wide image. That page just wasted a lot of your cellular data because your screen can't do anything with all that extra resolution. Ideally, the browser should get a version of the image that is just a little wider than your screen size, say 325 pixels. This ensures a high resolution image without wasting data. And best of all, the image will load faster. Responsive images allow browsers to search for different image resources on different devices. If you are not using an Image CDN, you must save multiple dimensions for each image and specify them in the
srcset attribute. the
w value tells the browser the width of each version. Depending on the device, the browser can choose the appropriate one:
< img src = " small.jpg " srcset = " small.jpg 500w, medium.jpg 1000w, large.jpg 1500w " alt = " … " >
Preloading allows you to inform the browser about critical resources that you want to load as soon as possible, before they are detected in HTML. This is especially useful for resources that cannot be easily discovered, such as fonts included in style sheets, background images, or resources loaded from a script.
< link rel = " preload " as = " image " href = " important.png " >
Responsive images + preloading = faster image uploads
Responsive images and preloading have been available for the past few years, but at the same time something was missing: there was no way to preload responsive images. Starting in Chrome 73, the browser can preload the correct variant of responsive images specified in
srcset before i discover the
To preload responsive images, new attributes were recently added to the
imagesizes. They are used with
and matches the
sizes syntax used in
For example, if you want to preload a responsive image specified with:
< img src = " wolf.jpg " srcset = " wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w " sizes = " 50vw " alt = " A rad wolf " >
You can do it by adding the following to your HTML
< link rel = " preload " as = " image " href = " wolf.jpg " imagesrcset = " wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w " imagesizes = " 50vw " >
This starts a request using the same resource selection logic as
sizes will apply.
Dynamically Injected Responsive Image Preload
Let's say you are dynamically loading heroic images as part of a slideshow and you know which image will display first. In that case, you probably want to avoid waiting for the script before loading the image in question, as that would delay when users can see it.
You can inspect this problem on a website with a dynamically loaded image gallery:
- Opened this sample website in a new tab.
Control + Shift + J(or
Command + Option + Jon Mac) to open DevTools.
- Click on the Net tongue.
- At Constriction drop down list, select Fast 3G.
- Turn off the Disable cache box.
- Reload the page.
preload It helps here because the image starts loading early and is likely already there when the browser needs to display it.
To see the difference preloading makes, you can inspect the same dynamically loaded image gallery but with the first image preloaded following the steps in the first example.
An alternative way to avoid the problem would be to use a brand-based carousel and have the browser preloader collect the necessary resources. However, this approach may not always be practical. (For example, if you are reusing an existing component, which is not brand-based.)
Preloading Background Images with Image Set
If you have different background images for different screen densities, you can specify them in your CSS with the
image-set syntax. The browser can then choose which one to display based on the DPR.
background-image : image-set ( "cat.png" 1x , "cat-2x.png" 2x ) ;
The above syntax ignores the fact that vendor prefixes are required for this feature in Chromium and WebKit-based browsers. If you plan to use this feature, you should consider using Autoprefixer to address that automatically.
The problem with CSS background images is that the browser discovers them only after it has downloaded and processed all the CSS on the page.
, which can be a lot of CSS ...
You can inspect this problem on a sample website with responsive background image.
Responsive Image Preloading provides a simple, piracy-free way to load those images faster.
< link rel = preload href = cat.png as = image imagesrcset = " cat.png 1x, cat-2x.png 2x " >
You can inspect how the above example behaves with Preloaded customizable background image.
Responsive image preloading in action
Preloading your responsive images can speed them up in theory, but what do you do in practice?
That gave me the following results for no preload and to image preload. Looking at the raw numbers, we see that Start Render stayed the same, the speed index improved slightly (273 ms, as the images arrive faster, but they do not occupy a large part of the pixel area), but the actual metric that captures the difference is the Last painted hero metric, which improved by 1.2 seconds. 🎉🎉
Of course, nothing captures the visual difference like a filmstrip comparison:
The Web Performance Working Group is talking about adding a preload equivalent to
sizes, but not the
element, which addresses the "art direction" use case.
Why is this use case "neglected"?
While there is interest in solving that use case as well, there are still a number of technical problems to solve which means that a solution here would have significant complexity. On top of that, it seems like for the most part the use case can be addressed today, even if in a hacky way (see below).
Given that, Web Performance WG decided to send
srcset first and see if the demand for equivalent
picture support arises.
If you are in pre-charge condition
you may be able to use the following technique as a solution.
Given the following scenario:
< picture > < source src = " small_cat.jpg " media = " (max-width: 400px) " > < source src = " medium_cat.jpg " media = " (max-width: 800px) " > < img src = " huge_cat.jpg " > picture >
Element logic (or image source selection logic, to be precise), would be to go over the
half attributes of the
items in order, find the first one that matches and use the attached resource.
Because receptive preloading has no notion of "order" or "first match", breakpoints should be translated into something like:
< link rel = " preload " href = " small_cat.jpg " as = " image " media = " (max-width: 400px) " > < link rel = " preload " href = " medium_cat.jpg " as = " image " media = " (min-width: 400.1px) and (max-width: 800px) " > < link rel = " preload " href = " large_cat.jpg " as = " image " media = " (min-width: 800.1px ) " >
Responsive image preloading gives us exciting new possibilities to preload responsive images in ways previously only possible through hacks. It's an important new addition to the speed-conscious developer's toolbox and allows us to make sure that the important images we want to show our users as soon as possible will be there when we need them.