Your speed report has a line you did not expect: “Largest Contentful Paint image was lazily loaded.” You thought lazy loading was the thing that made pages faster. You may even have switched it on specifically to please the same report. Now it is telling you the main photo on the page is arriving late because of it.
Both things are true. Lazy loading is one of the most useful speed features a site can have, and it is also very easy to apply to the wrong images. Here is lazy loading images explained in practical terms: what it does, what WordPress already does for you, and how to make sure it helps rather than hurts.
Lazy loading images explained: what it actually does
Without lazy loading, a browser fetches every image on a page as soon as it finds it in the HTML, including the ones at the very bottom that the visitor may never scroll to. On a long page with a gallery, a team section and a footer full of logos, that is a lot of downloading competing with the content at the top.
With lazy loading, images further down the page wait. The browser loads them shortly before they scroll into view. The visitor sees the top of the page sooner, and people who leave early never download the rest at all, which also saves them mobile data.
The key word is “further down”. Lazy loading is meant for images that are not visible when the page first opens. Applied to an image that is visible straight away, it adds a delay instead of removing one.
Native lazy loading: a single attribute
Modern browsers can do this themselves. An image tag with the attribute loading=”lazy” tells the browser it may postpone that image until it is close to the screen. All current major browsers support it. No script is needed, nothing breaks if the visitor has JavaScript turned off, and the browser decides the right distance at which to start loading based on the connection.
The same attribute works on iframes, which matters for embedded maps and videos. Our post on YouTube embeds that slow a page explains why iframes deserve extra care beyond lazy loading.
Script-based lazy loading
Before browsers supported the attribute, lazy loading was done with JavaScript. The real image address was hidden in an attribute such as data-src, a placeholder or blank image was shown, and a script swapped them over as the visitor scrolled. Many plugins still offer this method, sometimes alongside the native one.
It still works, but it has costs. The script itself has to download and run, images do not appear at all if the script fails, and some other plugins (image converters, galleries, sliders) do not recognise images whose address has been moved to data-src. On most sites today the native attribute is the simpler choice.
What WordPress does on its own
WordPress has added the native loading=”lazy” attribute to images and iframes in post content for several years now, without any plugin. Over later versions it has become smarter about the first images on the page: it tries to leave the first large image out of lazy loading, and it can mark the likely main image with a fetchpriority hint so the browser requests it early.
That logic works well on a standard blog post. It has limits on other pages:
- It has to guess. WordPress cannot see your layout. If a theme puts a logo, a menu icon and a small banner before the real hero image, the guess can land on the wrong one.
- Themes and page builders output their own images. A hero section built in a page builder may use the builder’s own lazy loading setting, which can override what WordPress would do.
- Plugins add another layer. Speed plugins often apply their own lazy loading on top. Two systems acting on the same image can produce strange results.
So it is worth checking what is really happening on your key pages rather than assuming the default is right.
The above-the-fold mistake
“Above the fold” means the part of the page visible before any scrolling. On most business sites, the largest thing there is a photo: a hero banner, a featured image or the first product. Google’s Largest Contentful Paint metric often ends up measuring exactly that image.
If that image is lazy loaded, the browser deliberately holds it back. It first works through the HTML, the CSS and often some scripts, calculates the layout, and only then realises the image is in view and starts downloading it. On a phone, that can turn a quick page into one where the main picture appears noticeably after everything else. Our post on improving Largest Contentful Paint covers the other causes of a slow main image; this one is often the easiest to fix.
How to check your hero image
- Run the page through PageSpeed Insights on mobile. Look for the warning that the LCP image was lazily loaded (newer versions of the report fold this into an insight about the LCP request), and note which element it names as the LCP.
- On the page, right-click that image and choose Inspect. Look at the image tag. If it has loading=”lazy”, or a data-src attribute and a lazy class added by a plugin, it is being lazy loaded.
- Check the same image at desktop width too. The first visible image can differ between mobile and desktop layouts.
How to fix it
- In a speed plugin that adds lazy loading, use its exclusion setting. Most offer a field to exclude images by file name or CSS class, or an option to skip the first one or two images on each page.
- In a page builder, look at the image or section settings for the hero. Some builders have their own lazy load switch per image, or a global performance setting.
- If the hero is a CSS background image rather than a normal image, lazy loading by attribute is not the issue, but a script may still be delaying it. Check your plugin’s settings for background image lazy loading.
- After excluding it, check the speed test again. The warning should go, and LCP on mobile often improves.
Images that should not be lazy loaded
- The main hero or banner image on each page.
- The site logo, if it is an image near the top.
- The featured image at the top of a blog post.
- The main product image on a product page.
- The first row of product thumbnails on a shop page, if they are visible without scrolling on common screen sizes.
Everything below that, galleries, testimonials with photos, logo strips, footer images, is a good candidate.
Lazy loading and layout jumps
When an image loads late, the browser needs to know how much room to leave for it. If the image tag has no width and height, the browser leaves no space, and when the picture arrives everything below it jumps down. Visitors lose their place, tap the wrong link, and Google’s layout shift metric gets worse.
WordPress normally adds width and height to images inserted through the editor. Problems tend to come from theme templates, page builder widgets and custom code that leave them out. If your pages jump as you scroll, our guide to fixing cumulative layout shift walks through finding the cause.
What lazy loading does not cover
- CSS background images. The loading attribute only applies to image tags and iframes. Background images in a stylesheet load according to the CSS, unless a plugin script handles them.
- Images controlled by sliders and galleries. Slider scripts often load all slides themselves, regardless of lazy settings. Check the slider’s own options.
- Images added by scripts after the page loads. Social feeds and review widgets insert images through JavaScript and follow their own rules.
- File size. Lazy loading changes when an image downloads, not how heavy it is. A huge photo is still huge when the visitor scrolls to it.
For the other image problems, start with our overview of which images are slowing a site down, and for speed beyond images, see the website speed and performance guide.
How to confirm it is working
Open the page in Chrome, press F12 and go to the Network tab with the Img filter on and “Disable cache” ticked. Reload without scrolling. You should see the images at the top load, and the ones lower down missing from the list. Now scroll slowly. New image requests should appear as you approach each section. If every image appears in the list immediately, lazy loading is not working on that page, or a slider or script is loading everything regardless.
If you run several plugins that each offer to lazy load images, choose one and switch the feature off in the others. One system, set up deliberately, is easier to reason about than three overlapping ones.
Frequently asked questions
Does lazy loading images affect SEO?
Native lazy loading with the loading attribute is fine for search engines, because the real image address stays in the HTML. Script-based methods that hide the address in a data attribute can cause problems if the crawler does not run the script. The bigger SEO risk is lazy loading the main image, which slows Largest Contentful Paint.
Should I lazy load images on a short page with only two or three pictures?
If all the images are visible without scrolling, lazy loading them gives no benefit and can delay them. If one or two sit lower down, lazy loading those is still sensible. The rule is the same on every page: images in the first view load normally, images further down can wait.
Why do images appear blank or grey for a moment when I scroll?
The browser started loading them only as you approached, and on a slow connection or with large files the download takes a moment. Smaller, properly sized images reduce the gap. Some script-based methods also start too late. Native lazy loading usually begins earlier, based on the visitor’s connection speed.
Can I lazy load images in WordPress without a plugin?
Yes. WordPress already adds native lazy loading to images and iframes in post content. A plugin is only needed if you want to change which images are excluded, cover images output by your theme or builder, or lazy load CSS background images. Check what your theme does before adding anything.
A hero image that is no longer lazy loaded but still arrives late points to something else in the page. Our speed optimisation service traces that kind of delay, from server response through to the last image request.
Next in this series: Responsive Images srcset: Smaller Images for Phones