Using 'fetchpriority' To Optimize HTML Image Loading
The fetchpriority
HTML attribute is starting to have enough browser support for usage in production environments. If a browser doesn't support it, it simply does not get used. There is no downside to using it, unless you use it wrong. This is an in-depth look into using it with <img>
and <picture>
elements via different use case perspectives.
Here's a code example of using high fetch priority with a regular img element:
<img src="/hero-image.jpg" fetchpriority="high" loading="eager" height="300" width="200" alt="..." >
And here's the same example with low fetch priority:
<img src="/regular-image.jpg" fetchpriority="low" loading="lazy" height="300" width="200" alt="...">
Do note that the loading attribute usage with the fetchpriority one might not be as black and white as the examples might show, and the next use case examples should give you an idea of why.
Different use cases for fetchpriority="high" and fetchpriority="low"
Above the fold
This use case is the most obvious: use the high priority to images that are above the fold. This includes images such as hero image and header logo, which are both most likely above the fold. You should combine the high fetchpriority with loading="eager"
attribute, making sure that browser will not try lazy loading it. This will speed up loading the first paint, giving you better user experience, and better Largest Contentful Paint and First Contentful Paint scores on Lighthouse.
Image carousel
Let's have a quick look at this illustration of an image carousel/slider design with a large slider image and several smaller thumbnails under it:
As you can see, all of the images have loading="lazy"
, making the images get lazy loaded, as this section is under the first fold. However the largest image still has fetchpriority="high"
, and small thumbnails have fetchpriority="low"
. Why?
The reason for that is that once user user scrolls close enough the image slider, the lazy loading will kick in and start loading the images. However the largest image should load quicker than the small thumbnails, as none of your users will prefer having to look at the small thumbnails while the large image loads. Giving the large image priority over the small thumbnails will make sure it loads as quick as possible.
The slider's large images after the first one can be set as fetchpriority="auto"
or with no fetchpriority attribute at all, as long as they also have loading="lazy"
.
Popup image
If you have a button or a small thumbnail that upon clicking should open a large popup image, it should be lazy loaded but still prioritized upon loading. Here the way you load the image will change what combination of loading and priority you should use.
If the image is part of the HTML DOM already and you're just hiding it with CSS, give it loading="lazy"
to prevent it being loaded before appearing on viewport (before user interaction), but also give it fetchpriority="high"
so that once it appears on the viewport upon a click, it loads with highest priority.
But if the popup image loads via JS logic, for an example useState via React, you can freely give it both loading="eager"
and fetchpriority="high"
to maximize it's quick loading time. It won't appear on the DOM without the user action happening, which means that the eager loading will not make it be loaded instantly on page load, it will only be loaded when it truly is part of the DOM.
Using low priority, even when above the fold
Let's say you have a hero image that changes via a CSS or JS animation - first one image is shown, then animation happens, and then a second image is shown.
Here it makes sense to give both loading="eager"
, as they are above the fold and should not be considered for lazy loading. However it does make sense to give the first image high fetchpriority, and the second one low fetchpriority. This make it so that as the first image will be shown first, the second image shouldn't impact its loading time. When the first image is loaded or hsa been loading for a bit, then the second image should start loading. This way the second image will be already loaded when it gets shown. If you were to use lazy loading for the second image, there's a good chance that it will be shown before it has been loaded, as browser is unsure when it should be displayed. Browsers are optimized, but they can't see in the future! This is why the fetchpriority was made, to give you better control over the loading process.
When to not give fetchpriority attribute at all
It is not recommended to specify the fetchpriority attribute at all for "regular" images, such as images on an article or regular "image next to text" sections on a layout. Just let lazy loading do its job with loading="lazy" and let browsers load them with the default fetchpriority. The fetchpriority property was made to solve more complicated loading solutions and not regular image layouts.
Last words on combining fetchpriority with the loading attribute
The fetchpriority is just a recommendation for the browser, giving high priority does not force browser to load images and giving low priority won't block loading them. It just gives additional context on image loading, and specifying loading="eager" and loading="lazy" will just become more important for solving browser's question "when should I start loading this?". If you specify the fetchpriority, but not the loading attribute, even low priority images under the fold can start slowing down the above the fold image loading, as depending on your browser they might not get lazy loaded by default.
Using fetchpriority outside images
This article has been all about using the fetchpriority with images, but it can also be used for things outside images too, for an example scripts, iframes and more. You can have further reading of its non-image capabilities with these articles: