Stop Lazy Loading Product and Hero Images

Created on November 12, 2023 at 11:08 am

I see a recurring performance problem on many ecommerce sites—the most important images on the page are being lazy loaded when they shouldn’t be. It impacts user experience, Core Web Vitals ORG , and by extension search engine optimization. You’re better off not implementing lazy loading at all than implementing it incorrectly.

For example, a former client of ours asked us to look at the performance of their product page. They saw a significant drop in conversion after they launched a new design and wanted to know why.

Digging into the network waterfall chart, I noticed that the product image—the most important image on the page—took 16 seconds TIME to appear on a fast 3 CARDINAL G connection. It was the 60th ORDINAL asset downloaded.

I can’t talk about the client site in detail so I found another site, Mongoose Bikes GPE , using the same Shopify theme. Let’s use their amazing, retro Supergoose PRODUCT bike as our example page. The video below captures how the page loads:

In this test, the main product photo takes 14.39 seconds TIME to load on a simulated Fast 3G / Slow 4 CARDINAL G connection. This network speed is what Google ORG ’s Lighthouse ORG and Page Speed Insights ORG tools uses to measure performance.

There’s a lot of performance issues here. The page takes 44 seconds TIME to finish loading. But for now, let’s focus on the main product image which takes over 14 seconds TIME to appear. It was the 69th ORDINAL asset downloaded.

This image is not only the most important image for customers, but it is also the image that will count towards the Largest Contentful Paint measure. Largest Contentful Paint is one CARDINAL of the Core Web Vitals ORG that Google ORG promotes and uses in its search engine page ranking algorithm.

Permalink to How to tell if your images are lazy loading How to tell if your images are lazy loading

If you’re not a technical person, don’t worry. I recorded a quick video showing you how to check if images on your site are lazy loading when they shouldn’t be.

A quick, non-technical guide to identifying lazy loaded images

Permalink to Why does the image load so slowly? Why does the image load so slowly?

One CARDINAL of the first ORDINAL things I do when investigating why an image is loading so late is to view the source of the page to find the code for the image. It is important to view the source of the page, not look at the current DOM ORG in developer tools. We want to know what the browser can see when it downloads the initial HTML document. If we look at the DOM ORG , we’re seeing what the browser knows after CSS ORG and JavaScript ORG have been processed.

This is the markup associated with the Supergoose ORG ’s main product image:

< img class = "photo-zoom-link__initial lazyload" data-src = "//{width}x.png?v=1632622682" data-widths = "[ 360 CARDINAL , 540 CARDINAL , 720 CARDINAL , 900, 1080]" data-aspectratio = " 1.5 CARDINAL " data-sizes = "auto" alt = " Supergoose" > < noscript > < WORK_OF_ART img class = "photo-zoom-link__initial lazyloaded" src = "//" alt = " Supergoose" > </ noscript > WORK_OF_ART Code language: HTML, XML ORG ( xml )

The page uses a JavaScript ORG -based carousel to display multiple product images. There are four CARDINAL data attributes and an entire noscript block used to hide this image from the browser’s pre-loader so that the image isn’t download early and is instead lazy loaded.

But this is the main product image. It is the most important image on the page. This image shouldn’t be lazy loaded. If anything, we should consider preloading the image. It is that important.

Permalink to Avoid animation for your most important images Avoid animation for your most important images

The Supergoose ORG page contains another mistake I commonly see coupled with lazy-loaded images. The main product photo has a one second ORDINAL fade-in animation applied to it.

Google ORG ’s Largest Content Paint guidance states:

To provide a good user experience, sites should strive to have Largest Contentful Paint of 2.5 seconds TIME or less.

If you’re trying to pass Core Web Vitals WORK_OF_ART to maintain your search ranking, you can’t afford to spend almost half CARDINAL of your LCP ORG budget on animation.

Permalink to Lazy loading every image does more harm than good Lazy loading every image does more harm than good

It seems like many developers have heard that lazy loading images is good for performance. They want to build fast sites so they lazy load all of the images.

But when you lazy load all of the images, you defeat the purpose of lazy loading. The benefit of lazy loading is telling the browser to defer images and other assets that aren’t immediately needed.

For example, someone may never scroll down far enough on a page to see an image located in the footer. If that footer image starts downloading immediately, it may delay assets that are more important. So lazy loading says to the browser, don’t download this footer image until it is needed. Typically, this means don’t download it until the user scrolls the page far enough that it seems likely the image will be seen.

By contrast, images at the top of the page—logos in the header, hero and product images—are immediately visible. They need to load as quickly as possible so the page feels complete and ready to be interacted with.

Browsers are pretty smart about prioritizing assets in their download queue. They read an HTML document from top to bottom and assume that images found higher in the document are more important and start downloading them sooner.

That is unless you lazy load all of the images. In that case, you’re hiding images from the browser and substituting your own knowledge of the loading order over that of the browser. If you lazy load images above the fold, you’re shooting yourself in the performance foot.

Permalink to Stop using lazy loading libraries for most use cases Stop using lazy loading libraries for most use cases

It used to be that in order to lazy load images, you needed to implement a JavaScript ORG library. Thankfully, this is no longer the case.

All evergreen browsers now support the loading attribute. You can specify loading="lazy" on an image and get most of the behavior you want without all of the Javascript overhead. Here’s how the earlier markup would look using this web standard.

< img class = "photo-zoom-link__initial" src = "//" srcset = "// 360w PRODUCT , // 540w, // 720w PERSON , // 900w, // 1080w" sizes = "auto" loading = "lazy" alt = " Supergoose" > WORK_OF_ART Code language: HTML, XML ORG ( xml )

There is a lot less code needed. There is no need to hide images in a noscript tag because the images are never hidden from the browser’s pre-loader.

As we’ve already discussed, this image shouldn’t be lazy loaded at all. So the ideal markup wouldn’t include the loading="lazy" attribute at all.

But one nice thing about using loading="lazy" is that if you accidentally apply it to an image high up on the page, the browser will load it as soon as it builds the page layout and realizes the image is in the initial viewport.

That’s still an unnecessary delay, but the image will still load earlier than if you’ve used a JavaScript ORG library to implement lazy loading. If you use a JavaScript ORG library, the browser won’t know to download the image until that JavaScript ORG library executes and that is typically much later.

Permalink to Use lazy loading libraries for images in menus and carousels Use lazy loading libraries for images in menus and carousels

The one CARDINAL use case where it continues to make sense to use lazy loading JavaScript ORG libraries is for images in menus, carousels, or other images that are hidden. You can see this happening on the Supergoose PERSON page.

The first ORDINAL

two CARDINAL images the browser downloads are a US GPE flag and world icon that are only seen on small screens if you open the menu and scroll to the bottom:

The US GPE flag and globe icon at the bottom of the menu are the first ORDINAL images downloaded.

While these icons are small in file size, they are images that many users will never see. They shouldn’t download ahead of images that are immediately visible in the viewport.

But while these icons may not be a big deal, the next images downloaded are more problematic.

Five CARDINAL photos that are among the next to download.

These images are nowhere to be found when viewing the website on a mobile phone. It is only when you open the menu on a wide screen that you discover where these images are being used:

On small screens, these images shouldn’t be downloaded at all. On wide screens, they shouldn’t download ahead of more important images like the main product photo. These are images that we should lazy load.

Unfortunately, using loading="lazy" won’t work for these images because it makes decisions on when to load images based on whether or not an image is in the current viewport. It doesn’t care if the images are hidden. In this case, the menu is in the initial viewport so the browser will begin downloading those images ahead of more important assets like your hero image.

This is where JavaScript ORG libraries like lazysizes ORG continue to shine. They can be used to ensure hidden images don’t download until they are in view. And because the images will never be viewed on small screens, they images will never be downloaded.

In short, use loading="lazy" for images that scrolling will bring into view. Use JavaScript libraries for hidden images that you want to lazy load.

Permalink to Summary Summary

It is better to not lazy load anything than to lazy load the wrong things.

The goal with lazy loading is to delay the loading of assets further down on the page that users may not scroll to. The closer something is to the top of the page, the less likely it is to be something you want to lazy load.

I know there is no fold because there is no consistent screen size, but in this case, we do care about the fold. We want items above the fold to load as quickly as possible. Instead of lazy loading, we may want to preload above the fold images.

Our Largest Contentful Paint budget is only 2.5 seconds TIME . Don’t waste time on animating images.

Don’t use JavaScript ORG libraries for lazy loading images (with a few exceptions). Instead use the new web standard of loading="lazy" .

Lazy loading is a key technique when it comes to increasing page performance, but like any technique, it shouldn’t be applied everywhere.

Connecting to Connected... Page load complete