
Lazy loading images is one of those optimizations that sounds like a free win. Defer offscreen images, save bandwidth, speed up the page. Mostly true. But there is one image on almost every page where lazy loading is the wrong call: the hero image, the header banner, the big photo at the top of a blog post. Load that one lazily and you can watch your Largest Contentful Paint (LCP) score go from good to bad in one deploy.
This guide covers how native lazy loading actually works, why the above-the-fold exception matters, and the fetchpriority fix that tells the browser which image to grab first.
How native lazy loading works
Modern browsers support the loading="lazy" attribute on img and iframe tags. When present, the browser defers fetching that resource until it is close to entering the viewport. WordPress core has added this attribute automatically to most content images since the 5.x era, and it carries forward into the current WordPress 6.x releases.
This is genuinely useful. A long article with fifteen images does not need to fetch all fifteen on initial page load. Lazy loading the ones the visitor has not scrolled to yet reduces initial payload, speeds up time to interactive, and lowers bandwidth costs. For anything below the fold, it is close to a no-brainer.
The mistake: lazy loading the hero image
The problem is that WordPress core’s automatic lazy loading logic is a heuristic, not a guarantee. It often looks at position in the markup rather than true visual position, and themes, page builders, and cache plugins can all interfere with the order images render in. The result: the large image at the very top of the page, the one that is almost certainly your LCP element, sometimes gets tagged with loading="lazy" when it should be loaded immediately.
Remember what LCP measures: the render time of the largest visible content element, usually a hero image or a large block of text, as experienced by a real visitor loading the page for the first time. Core Web Vitals treats an LCP of 2.5 seconds or less as good. If the browser is told to wait on the hero image until it “notices” it needs it, you have added a delay to the single metric most tied to perceived speed and to search performance.
The fix has two parts: stop lazy loading anything above the fold, and tell the browser to prioritize the one image that matters most.
The fix: fetchpriority and eager loading
For any image visible in the initial viewport, especially the one likely to be your LCP element, you want two things:
loading="eager"(or simply omit the loading attribute) so the browser does not defer the fetchfetchpriority="high"so the browser’s resource scheduler treats it as a priority fetch relative to other assets competing for bandwidth, like fonts or render-blocking scripts
The two attributes solve different problems. Removing lazy loading stops the browser from waiting. Adding fetchpriority="high" pushes the request to the front of the queue even among non-lazy resources. Used together on your hero image, they consistently pull LCP timing forward.
Applying it in WordPress
If you are using a block theme or the Cover block for your hero, most current WordPress versions let you toggle off lazy loading for a featured image in the image block settings by removing the lazy load behavior, though the option surfaces differently across themes and versions. Where you need certainty, a small functions.php filter is the reliable route:
add_filter( 'wp_get_attachment_image_attributes', function( $attr, $attachment, $size ) {
if ( is_singular() && has_post_thumbnail() ) {
$thumb_id = get_post_thumbnail_id();
if ( $attachment->ID === $thumb_id ) {
$attr['loading'] = 'eager';
$attr['fetchpriority'] = 'high';
unset( $attr['loading'] ); // ensure no lazy attribute lingers
$attr['loading'] = 'eager';
}
}
return $attr;
}, 10, 3 );If your hero image is hardcoded in a theme template rather than pulled through the_post_thumbnail(), just edit the markup directly and add both attributes to that one img tag. You do not need a plugin for this, and adding one just to manage two HTML attributes is usually overkill.
Finding the images that need attention
Before you change anything, confirm which element is actually your LCP candidate. Run your homepage and your top landing pages through a Core Web Vitals field or lab tool and look at which element it reports as the LCP source. It is not always the obvious hero photo; on some templates it is a headline, on others it is a background image applied through CSS rather than an img tag (which needs a different fix entirely, since loading="lazy" has no effect on CSS backgrounds).
If you manage many pages and want a fast way to audit theme templates for stray lazy attributes, wp-cli is useful for scripting a search across your active theme’s files, though there is no built-in wp-cli command that inspects rendered HTML output. For that, pulling a handful of page URLs and grepping the response for loading="lazy" near the top of the markup will tell you quickly whether the fix landed where you expect.
How your caching layers interact with this
If you run LiteSpeed Cache alongside a LiteSpeed or OpenLiteSpeed server, check its image optimization and lazy load settings. Most versions let you exclude specific images or classes from lazy loading, which is exactly what you want for the hero. Set the exclusion once and it survives cache purges and rebuilds.
On the network side, Cloudflare sitting in front of your origin does not touch the lazy loading attribute itself since that is applied server side, but it does affect how fast the hero image reaches the visitor once requested. Combine a correctly prioritized fetch with Cloudflare’s edge caching and HTTP/3, and the actual bytes for that hero image travel a shorter, faster path than a request going straight to your origin server.
Takeaway
Lazy loading is not the enemy of speed, careless lazy loading is. Keep it for everything below the fold, where it genuinely helps. Strip it from your hero image, add fetchpriority="high", and verify the change against your actual LCP element rather than guessing. It is a small edit with an outsized effect on the one Core Web Vitals number visitors actually feel.