Stop Lazy Loading Product and Hero Images

By admin
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 = "//www.mongoose.com/cdn/shop/products/M21_20U_Supergoose-BLK_PD_{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 = "//www.mongoose.com/cdn/shop/products/M21_20U_Supergoose-BLK_PD_740x.png?v=1632622682" 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 = "//www.mongoose.com/cdn/shop/products/M21_20U_Supergoose-BLK_PD_540x.png?v=1632622682" srcset = "//www.mongoose.com/cdn/shop/products/M21_20U_Supergoose-BLK_PD_360x.png?v=1632622682

360w
PRODUCT

, //www.mongoose.com/cdn/shop/products/M21_20U_Supergoose-BLK_PD_540x.png?v=1632622682 540w, //www.mongoose.com/cdn/shop/products/M21_20U_Supergoose-BLK_PD_720x.png?v=1632622682

720w
PERSON

, //www.mongoose.com/cdn/shop/products/M21_20U_Supergoose-BLK_PD_900x.png?v=1632622682 900w, //www.mongoose.com/cdn/shop/products/M21_20U_Supergoose-BLK_PD_1080x.png?v=1632622682 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.