WordPress has lazy-loaded images natively since version 5.5, so for most sites the job is not turning lazy loading on but making sure it is not slowing down the one image that matters most: the largest image above the fold. Done right, lazy loading cuts page weight and improves load times on image-heavy pages. Done wrong, it delays your Largest Contentful Paint (LCP) and hurts the Core Web Vitals score it was supposed to help. This guide explains how WordPress handles lazy loading today, when to leave it alone, when to disable it for specific images, and how to check the result.
What Lazy Loading Does
Lazy loading defers the download of images (and iframes) that are outside the visitor’s viewport until they scroll near them. A long article with 30 images loads the 2 or 3 visible ones immediately and fetches the rest as needed. The browser does less work up front, the page becomes interactive sooner, and visitors who never scroll to the bottom never download those bytes at all.
The trade-off is timing. An image that is lazy-loaded but actually visible on first paint starts downloading later than it should, because the browser waits to confirm it is in view before requesting it. For the hero image or any large image at the top of the page, that delay shows up directly in LCP.
How WordPress Handles It Natively
WordPress 5.5 (August 2020) began adding the HTML attribute loading="lazy" to images in post content, and 5.7 extended it to iframes. No plugin or JavaScript is involved; the browser does the work. Three details matter:
Width and height are required. WordPress only adds loading="lazy" to an image tag that already has width and height attributes. That is deliberate: the browser needs the dimensions to reserve space so the layout does not jump when the image arrives (which would hurt Cumulative Layout Shift). Images inserted through the editor get these attributes automatically; images hard-coded in a theme without dimensions do not get lazy-loaded.
The first images are skipped. Since WordPress 5.9, the first content image (and, since 6.3, a small number of images likely to be above the fold) is intentionally not lazy-loaded. WordPress 6.3 also began adding fetchpriority="high" to the image it judges to be the LCP candidate, telling the browser to fetch it before other resources.
It only applies to content WordPress renders. Images output by the_content(), the_post_thumbnail(), block themes, and widgets are covered. Background images set in CSS, images injected by JavaScript sliders, and markup a plugin builds by hand are not.
When Native Lazy Loading Is Enough
For most business sites on a well-built theme, it is. The defaults are conservative, the LCP image is handled, and there is nothing to install. If your PageSpeed Insights report does not flag “Defer offscreen images” or “Largest Contentful Paint image was lazily loaded”, leave it alone and spend your effort on image compression and format instead. Serving properly sized WebP or AVIF images usually saves more bytes than any lazy-loading change.
When to Exclude an Image From Lazy Loading
The classic mistake is a hero image, logo, or above-the-fold product image carrying loading="lazy". PageSpeed Insights reports this explicitly as “Largest Contentful Paint image was lazily loaded.” Fix it at the source rather than with a plugin setting.
If the image is in a theme template, write the tag without the lazy attribute and add priority instead:
<img src="hero.webp" width="1600" height="900" alt="…" fetchpriority="high">
If the image comes from a WordPress function such as the_post_thumbnail(), pass the attributes directly:
the_post_thumbnail( 'full', array( 'loading' => 'eager', 'fetchpriority' => 'high' ) );
For finer control across the site, WordPress 6.3 and later provide the wp_get_loading_optimization_attributes filter, which lets you decide per image and context whether it receives loading, fetchpriority, and decoding attributes. On older versions (5.5 to 6.2) the equivalent was wp_img_tag_add_loading_attr. Both should be used surgically; the goal is to eager-load the handful of images that are visible on first paint, not to disable lazy loading everywhere.
How to Disable Lazy Loading Entirely
You rarely should, but if a page template, slider, or third-party script conflicts with it, one filter turns it off site-wide:
add_filter( 'wp_lazy_loading_enabled', '__return_false' );
Put that in a small custom plugin or the theme’s functions.php. Then re-test Core Web Vitals on your longest, most image-heavy page; you will usually find you have traded a small problem for a larger one and want to re-enable it with targeted exclusions instead.
Plugins and JavaScript Lazy Loading
Before native support existed, lazy loading meant a JavaScript library: the image tag carried a placeholder in src and the real URL in data-src, and a script swapped them when the image scrolled into view. Some caching and optimization plugins, including WP Rocket, still offer this because it can also handle CSS background images and iframes more aggressively.
Running both approaches at once is a common source of trouble: the browser’s native lazy loading and a script both trying to manage the same images, images that never load when JavaScript fails, and the LCP image delayed twice. If you enable a plugin’s lazy-load feature, make sure it either replaces the native behavior cleanly or is limited to the cases native lazy loading cannot reach. And always add your logo, hero image, and above-the-fold images to the plugin’s exclusion list.
How to Test the Result
Run the page through PageSpeed Insights and look at three things: the LCP element (it should not be lazy-loaded), the “Defer offscreen images” audit (offscreen images should be deferred), and the “Image elements do not have explicit width and height” audit (every image needs dimensions for lazy loading and CLS). In Chrome DevTools, the Network panel with “Img” selected shows which images load on first paint and which wait for scroll.
Lazy loading is one lever among several in page speed optimization. On the sites we rebuild, the bigger wins usually come from serving the right image size and format, removing page-builder markup, and controlling what loads in the head. When we moved Hoppr.ai from Squarespace to a custom WordPress theme, LCP fell from 15.2 seconds to 0.8, and lazy loading was a small part of that; the rest was building the page so there was less to load in the first place. If your Core Web Vitals are stubbornly orange or red, book a discovery call and we will tell you where the time is actually going.