LCP image lazy-loaded: when the hero image is told to wait
Lazy loading tells the browser not to fetch an image until it is near the viewport. That is right for images further down the page and wrong for the hero image, which is usually the Largest Contentful Paint element. Remove loading="lazy" from that one image and give it fetchpriority="high".
Google's threshold for a good LCP is 2.5 seconds or less. Core Web Vitals are a modest ranking input compared with relevance, but a slow hero image is among the cheapest LCP problems to fix.
What it looks like
Before
<img src="/wp-content/uploads/hero.jpg" width="1600" height="900" alt="Stoneware mugs on a shelf" loading="lazy">
After
<img src="/wp-content/uploads/hero.jpg" width="1600" height="900" alt="Stoneware mugs on a shelf" fetchpriority="high">
Why lazy loading hurts here
For an eager image, the browser's preload scanner finds the <img> while the HTML is still arriving and starts the download at once. For a lazy image, the browser must first lay out the page to know whether the image is near the viewport, and only then request it. On a slow connection that wait is significant. JavaScript-based lazy loaders are worse: the real URL sits in a data-src attribute, invisible to the preload scanner, until a script has downloaded, parsed and run.
Find your LCP element
- PageSpeed Insights. Run the URL and open the diagnostics. The "Largest Contentful Paint element" entry shows the element. Lighthouse has reported this problem under the name "Largest Contentful Paint image was lazily loaded"; newer versions fold it into their LCP request discovery insight.
- Chrome DevTools. In the Performance panel, record a page load; the LCP marker in the timings track identifies the element when you click it.
- By inspection. View source, find the first large image and read its attributes.
Test on a mobile viewport as well as desktop, since the LCP element often differs between them.
The LCP element may not be an <img> at all. If it is a CSS background image, the loading attribute does not apply, and the image is discovered late for a different reason; see the last section.
What WordPress does by default
WordPress adds loading="lazy" to images automatically, with safeguards for the top of the page:
- It leaves the attribute off the first few content images. The count is set by the
wp_omit_loading_attr_thresholdfilter, which defaults to 3. - It adds
fetchpriority="high"to the first sufficiently large image it encounters, where the area is at least 50,000 square pixels by default, and that image is never marked lazy.
So on a stock theme the hero is usually handled. The issue arises when something works outside that logic:
- Hard-coded attributes. A theme template or page-builder widget prints
loading="lazy"on every image itself. - A lazy-load plugin or optimisation feature that rewrites all images to
data-src, including the first. - Images added by blocks or shortcodes that bypass core's image functions, so no
fetchpriorityis added and the builder's own default applies. - Counting that does not match the layout. The logo, an avatar and a small icon can use up the first three "content images" in markup, leaving the visually dominant hero as the fourth and lazy.
- Sliders. The first slide is treated like the rest.
Fix it
In the block editor. WordPress decides automatically; if the hero is being marked lazy because several small images precede it, raise the threshold:
add_filter( 'wp_omit_loading_attr_threshold', function () {
return 5;
} );
In a theme template. When you print the hero yourself, pass the attributes explicitly:
echo wp_get_attachment_image( $hero_id, 'full', false, array(
'loading' => 'eager',
'fetchpriority' => 'high',
) );
In a lazy-load or performance plugin. Use its exclusion setting. Most offer "skip the first N images" or exclusion by CSS class or filename. Exclude the hero and the logo. If the plugin duplicates what WordPress already does natively, turning its image lazy loading off altogether is often the cleanest fix.
In a page builder. Look for a per-image "lazy load" toggle on the hero widget and switch it off, and check the builder's global performance settings for a first-image exclusion.
Use fetchpriority="high" on one image per page. Applied to many, it stops meaning anything.
Background images and other hidden heroes
A hero set with background-image in CSS is not found until the stylesheet has been downloaded and parsed. Two options:
- Replace it with a real
<img>positioned behind the text withobject-fit: cover. This is the better fix, since it also allowssrcsetand alt text. - Keep the background and add a preload hint in the head:
<link rel="preload" as="image" href="/wp-content/uploads/hero.jpg" fetchpriority="high">
Preload exactly the file the page will use at that viewport, or the browser downloads two images.
Do not swing too far
Keep lazy loading on everything below the fold. Removing it site-wide makes pages heavier at load and competes with the hero for bandwidth, which is what no lazy loading describes. The aim is one prioritised image at the top and lazy images beneath it. Our guide to improving Core Web Vitals in WordPress covers the rest of the LCP chain, from server response to image size.
Measure the change
View source and confirm the hero has no loading="lazy" and does have fetchpriority="high". Rerun PageSpeed Insights: the lazily-loaded audit should pass, and in the LCP breakdown the "load delay" portion should shrink. Lab numbers change immediately. The field data in Search Console's Core Web Vitals report is a rolling 28-day window of real visits, so allow about a month for it to reflect the fix.
Common questions
Should every above-the-fold image be eager?
Images visible without scrolling should not be lazy. Only the single most important one needs fetchpriority="high".
Is loading="eager" necessary?
Eager is the default when the attribute is absent. Writing it explicitly is useful mainly to stop other code adding lazy.
Will fixing this improve rankings?
It improves a Core Web Vitals metric, which Google uses as one of many signals. Expect a better experience first and, at most, a small ranking effect.
The hero is the first slide of a slider. What should I do?
Mark the first slide's image eager with high priority and keep the remaining slides lazy. Better still, consider whether a single static hero would serve visitors as well.