Optimize images for Core Web Vitals
Lean how images affect the Core Web Vitals en how to optimize them
How Images Can affect the Core Web Vitals?
Images play a significant role in enhancing the visual appeal of a website, but they can also have a significant impact on its loading speed. Core Web Vitals are a set of metrics that Google uses to measure the user experience of a website, and image optimization is a critical factor in achieving good scores. In this article, we will discuss how to optimize images for Core Web Vitals and improve your website's loading speed.
Table of Contents!
- How Images Can affect the Core Web Vitals?
- Understanding Core Web Vitals
- Which Core Web Vitals can images affect?
- Step 1: Optimize the HTML image element for speed
- Step 2: Ensure the image is enqueued for download as early as possible
- Step 3: Ensure the image is downloaded as fast as possible
- Step 4: Eliminate layout Shift!
- Step 5: Protect the main thread
- Step 6: Choose the right strategy for each image!
Understanding Core Web Vitals
Before we delve into image optimization, let's briefly review the Core Web Vitals. They are a set of user-centric metrics that measure the loading speed, interactivity, and visual stability of a web page. The three key metrics are:
Largest Contentful Paint (LCP): measures the loading speed of the largest element on the page.
First Input Delay (FID): measures the time it takes for the page to become interactive.
Cumulative Layout Shift (CLS): measures the visual stability of the page.
Which Core Web Vitals can images affect?
You might be surprised to learn that images can affect all of the Core Web Vitals. Images, if they are queued for download at a late time during rendering or if they are simply too large will usually result in a high LCP score. If image dimensions are not set or change during the loading phase images can also affect the CLS score. And finally, if image decoding takes up too much main thread work, they can even affect the INP. Let's take a closer look:
Largest Contentful Paint
One of the Core Web Vitals is Largest Contentful Paint (LCP), which measures how long it takes for the largest element on the page (such as an image or video) to become visible to the user. If an image is enqueued too late or takes too long to load, it can significantly slow down the page's LCP score.
Cumulative Layout Shift
Another Core Web Vital is Cumulative Layout Shift (CLS), which measures how much the content on a page shifts around as it loads. Images can cause layout shifts if they are not properly sized or if they are inserted into the page after it has already loaded, causing other elements to move around.
First Input Delay and INP
Finally, images can also impact the third Core Web Vital, the INP, which measures the time it takes for a page to visually respond after a users to interacts with a page. If there are too many large images that need to be decoded the page may take longer to respond to user interactions, leading to a poor INP score.
Step 1: Optimize the HTML image element for speed
Src attribute
Specifies the URL of the image. This property is essential, as it tells the browser where to find the image.
Width and height attribute
Specifies the width and height of the image in pixels. These properties are important for rendering the image correctly on the page, as they define the size of the image container and how the image fits inside it.
Alt attribute
Specifies alternative text for the image if it cannot be displayed. This is important for accessibility purposes, as it helps visually impaired users understand what the image is about. It's also important for search engine optimization (SEO), as search engines use the alt text to understand the content of the image.
Loading attribute (lazy loading)
Specifies how the browser should load the image (lazy, eager, or auto). This property is important for improving page performance, as it allows images to be loaded asynchronously and only when they are needed.
Srcset attribute
Sizes attribute
Decoding attribute
Fetchpriority attribute
The fetchpriority attribute specifies the priority of a resource's fetch relative to other resources on the page. The priority attribute can have one of three values: "high", "medium", or "low". A resource with a high priority is loaded before resources with medium or low priorities. A resource with a medium priority is loaded before resources with a low priority. Resources with the same priority are loaded in the order that they appear in the HTML.
Step 2: Ensure the image is enqueued for download as early as possible
The second thing to do, after you have optimized the html is look at image scheduling. In many cases, the biggest bottleneck, when it comes to images affecting the LCP metric is late scheduling. If a browser has a chance to download the LCP element early during the rendering process the image will be available to the browser as early as possible and the browser can start painting that element early in the rendering process.
Sound simple right? Well, how do we make sure the image is queued for download as early as possible.
Preload the LCP element
The most effective way to ensure an early download is to preload the image. Preloading the image is done with a simple tag at the start of the <head>
element. For example:
<link rel="preload" as="image" href="image.jpg">
This simple tag will tell the browser that we will need "image.jpg" pretty soon and the browser will start downloading this file immediately.
Eager load the LCP element
Use high fetchpriority
If, for some reason, you cannot preload the LCP element at least make sure the element has the fetchpriority attribute set to high. This will hint to the browser that in images is important to the page and the browser will downloading it with a high priority. Please note that using fetchpriority="high"
is usually not as efficient as preloading an image!
Avoid JavaScript based lazy loading
Step 3: Ensure the image is downloaded as fast as possible
The third thing to do is to make sure you are not wasting precious network resources on images that are larger than they should be. You can do this using responsive image, using compression and using new and faster image containers
Responsive images
Image Compression
New and faster image containers
Images are often one of the largest resources on a webpage, and they can significantly slow down the loading speed of a page if they are not optimized. Newer and faster image containers, such as the WebP and AVIF formats, can help reduce the file size of images without sacrificing their quality. This means that they can be loaded more quickly, which can improve the loading speed of the page.
Step 4: Eliminate layout Shift!
Images that change size while they are loading will cause a layout shift. It is as simple as that. There are 3 main reasons why images cause a layout shift (there are a lot more actually but these 3 are the most common ones)
1. Missing image dimensions
2. Styling issues
Usually images are prevented from growing larger than the viewport by a simple CSS trick
img{ max-width:100%;
height:auto; }
This is a great trick and you should use it. Unfortunately I regularly see variants of this trick that do cause a layout shift. For example by adding width:auto:
img{ max-width:100%;
height:auto; width:auto; }
This will make any image render with an auto width and height. This usually means the browser will render the image at 0x0px before the image has downloaded
3. Placeholders
Some JavaScript based lazy loading scripts use placeholders. If you use some sort of CSS trick like the above mentioned max-width:100% and height:auto then the autoheight of the square placeholder will not match the height attribute of the image. Basically the image will first render with the square placeholder at 720x720 and when the final image has downloaded it will render at 720*180
<img src="1x1placeholder.png" data-src="hero.png" width="720" height="180" style="height:auto;max-width:100%" >
Step 5: Protect the main thread
The next thing to make sure is that not too many images get decoded on the main thread at the same time. Usually this is not going to be a problem but I have seen it happen many times on product listing pages (where sometimes as many as 500 images compete for resources!).
The trick is to add decoding="async"
to all image to make sure these images can be decoded on a seperate thread. Also try to avoid this many image decoded all at once by adding loading="lazy"
to all below the fold and hidden images.
Step 6: Choose the right strategy for each image!
Image strategies for the LCP element
The LCP element is usually the most important visual element. So we need to really prioritize this one."
- Preload the image early in the head of the page with this code:
<link rel="preload" as="image" href="path-to-img.png">
- Tell the browser that this image should not be lazy loaded by setting
loading="eager"
or by omitting the loading attribute - Hint to the browser that this image should be downloaded with a high priority by using
fetchpriority="high"
(if you are preloading the image, you can skip this part) - Set
decoding="sync"
since this element is so important that we want to decode it on the main thread
Image strategy for logo's and other visible (non-LCP) images
Visible images should be loaded pretty soon during page load but preferably after the LCP element. We can achieve this by preloading the LCP element. That will give these visible images their natural, correct download order.
- Tell the browser that this image should not be lazy loaded by setting
loading="eager"
or by omitting the loading attribute - Set
decoding="async"
since this element can be safely decoded off the main thread!
Image strategy for below-the-fold images
All below-the-fold images should be lazy loaded. It is that simple! There are no exceptions!
- Tell the browser that this image should be lazy loaded by setting
loading="lazy"
- Set
decoding="async"
since this element can be safely decoded off the main thread!
Avoid background images
If you are using background images you need to reconsider. Background images cannot be lazy loaded and you cannot control the decoding property and you cannot set the fetchpriority. Background images are usually not responsive which will probably cost you a lot of bandwidth. But most important background images are usually discovered after the browser has downloaded the CSS files. This is almost never the right time to trigger an image download!
You can use normal image tags in combination with the CSS object-fit:cover to make normal images behave as background images!
Stop Guessing, Start Measuring
I use Core/Dash to optimize my clients sites. So Should You.
- Easy set up.
- Over 5000 happy clients
- Free trial, No strings attached