You added loading="lazy" to every image on your site because the performance guides said lazy loading saves bandwidth and improves page speed. Your Lighthouse score went up. Then your CrUX data came in, and LCP got worse — sometimes significantly worse. The problem is that lazy-loading the LCP image delays its loading by design. The browser’s native lazy loading withholds the image request until the element is near the viewport during scroll, but for above-the-fold images that are already in the viewport on initial load, this adds an artificial delay that directly inflates LCP. Blanket lazy loading is one of the most common self-inflicted LCP regressions in production, and the fix requires understanding which images must be excluded.
How Browser-Native Lazy Loading Delays Above-the-Fold Requests
When loading="lazy" is applied to an <img> element, the browser’s preload scanner skips that image entirely. Under normal circumstances, the preload scanner discovers <img> elements during its initial HTML scan and begins fetching them speculatively, well before the primary parser reaches them. This speculative fetching is one of the most significant built-in browser optimizations for image-heavy pages. Lazy loading explicitly opts out of this early discovery.
The Intersection Observer Timing Gap and Its LCP Impact
Instead of including the image in the initial resource loading waterfall, the browser defers the request until a multi-step process completes: download CSS, construct the CSSOM, perform layout calculations, determine the image’s position relative to the viewport, check connection type against internal distance thresholds, and only then initiate the download. On a fast connection, this adds 200-500ms of delay. On slower connections with constrained CPU (mid-tier mobile devices), the delay can exceed 1 second because layout calculation itself takes longer.
For the image that happens to be the LCP element, this artificial deferral translates directly to a higher LCP timestamp. The image would have started loading during HTML parsing without the lazy attribute; with it, the image cannot begin loading until layout confirms viewport proximity. Google’s Martin Splitt stated explicitly that lazy loading an immediately visible image is “almost guaranteed” to impact LCP negatively.
The 2025 Web Almanac reported that 10.4% of mobile pages still apply native lazy loading to their LCP image, with an additional 5.9% using JavaScript-based lazy loading on the LCP element. That represents roughly 1 in 6 pages actively delaying their most critical visual content. Data from CoreDash shows 79% of pages without lazy-loaded LCP images achieve “good” LCP scores, compared to only 52% for pages that lazy-load their LCP element — a 27-percentage-point gap directly attributable to this single misconfiguration.
Why Lighthouse Scores Improve While Field LCP Worsens
The disconnect between improving lab scores and worsening field metrics after blanket lazy loading creates persistent confusion. Lighthouse measures performance on a simulated single page load with predefined throttling. Lazy loading reduces the total number of image requests and bytes transferred during this simulated load, which improves metrics like Total Blocking Time and Speed Index. The overall performance score increases because these metrics carry significant weight in the Lighthouse scoring model.
Lighthouse does detect above-the-fold images and can flag lazy-loaded LCP images as an issue, but the overall score improvement from reduced total page weight often masks the specific LCP penalty in the aggregate number. Teams monitoring only the composite Lighthouse score see improvement and assume the change was beneficial across all dimensions.
Field data tells a different story. CrUX captures the 75th percentile LCP across real users on diverse devices and connections, where the lazy loading delay compounds with slower hardware and network conditions. A 300ms lazy-loading delay in lab translates to a 500-800ms delay for users on mid-tier Android devices with 3G effective connections. The variance in field conditions amplifies the penalty that lab simulation understates.
The Lighthouse audit “Largest Contentful Paint image was lazily loaded” specifically flags this pattern, but it appears as an individual diagnostic rather than a score-impacting failure. Teams that rely on the composite score rather than individual audit results miss the warning. The correct interpretation is that any improvement in total page weight from lazy loading must be weighed against the specific LCP regression for above-the-fold images.
The Correct Strategy: Eager Loading for LCP Candidates, Lazy for Everything Else
The optimal approach treats lazy loading as a selective optimization applied only to images outside the initial viewport, while explicitly excluding the LCP image and marking it with fetchpriority="high" to maximize its loading priority.
<!-- LCP image: eager load with high priority -->
<img src="/hero.webp" alt="Hero" fetchpriority="high" width="1200" height="600">
<!-- Below-fold images: lazy load -->
<img src="/gallery-1.webp" alt="Gallery" loading="lazy" width="400" height="300">
<img src="/gallery-2.webp" alt="Gallery" loading="lazy" width="400" height="300">
Identifying the LCP image requires checking CrUX or RUM data for the actual LCP element on each page template, because the LCP image varies by page layout, viewport size, and content configuration. A product page may have a product image as LCP on desktop but a heading as LCP on mobile. A blog post may have a featured image as LCP on one template and a text paragraph on another.
For responsive designs, the LCP image may differ between mobile and desktop viewports. If different images serve as LCP at different breakpoints, both candidates should be eagerly loaded. Using fetchpriority="high" on both is acceptable — the browser handles priority correctly even with multiple high-priority images, though limiting high-priority hints to genuine LCP candidates prevents priority inflation.
The loading="eager" attribute can be applied explicitly to override any framework or plugin that applies lazy loading by default, though omitting the loading attribute entirely achieves the same result since eager loading is the browser’s default behavior. The explicit attribute serves as documentation and as a safeguard against future changes in framework defaults.
CMS Auto-Applied Lazy Loading and Framework Default Pitfalls
WordPress introduced automatic loading="lazy" on all images starting in version 5.5, creating the largest single source of lazy-loaded LCP images on the web. The 2022 Web Almanac found that 72% of pages with a lazy-loaded LCP image were WordPress sites. WordPress 5.9 added a partial fix by skipping lazy loading on the first image in the content, and WordPress 6.3 further improved this by automatically applying fetchpriority="high" to the likely LCP image. However, these heuristics fail in common layout patterns.
The first-image-skip heuristic breaks when the LCP image is not the first image in the markup — a common occurrence in layouts where a logo or navigation icon appears before the hero image in DOM order. WordPress estimates the LCP image position using document order, but document order does not reliably predict visual prominence, especially when CSS reorders elements via flexbox or grid layouts.
Plugin and Theme Conflicts That Override Eager Loading Fixes
Third-party optimization plugins frequently override WordPress core behavior by applying their own lazy loading logic to all images, undoing the core heuristic improvements. Sites running WP Rocket, Autoptimize, or similar plugins must verify that the LCP image exclusion is configured correctly at the plugin level, not just at the theme template level.
JavaScript frameworks present a parallel challenge. Next.js, Nuxt, and other SSR frameworks may apply lazy loading through their image components. Next.js Image component applies loading="lazy" by default and requires explicit priority prop to override this behavior for above-the-fold images. Developers who use the component without the priority prop on their hero image introduce the same LCP regression as blanket WordPress lazy loading.
The operational challenge across all platforms is maintaining correct lazy-loading exclusions as templates change. A redesign that moves a new image into the above-the-fold position or changes the LCP element identity requires updating the lazy-loading configuration. Build-time viewport estimation heuristics, server-side critical-image detection, or continuous RUM monitoring for lazy-loaded LCP images are the reliable approaches. Manual configuration drifts as sites evolve.
Does the loading=”eager” attribute actively speed up image loading compared to omitting the loading attribute entirely?
No. The loading=”eager” attribute is the browser default behavior when no loading attribute is present. Setting it explicitly changes nothing about resource priority or fetch timing. Its value is declarative clarity in codebases where a CMS or framework applies loading=”lazy” automatically, overriding the default. The performance gain comes from preventing lazy application, not from eager adding any acceleration.
Can lazy-loading non-image elements like iframes affect LCP scores?
Yes, if an iframe contains the largest visible element in the viewport. Embedded video players, maps, or third-party widgets rendered inside iframes can become the LCP candidate. Lazy-loading that iframe delays the entire embedded content load, pushing LCP beyond the 2.5-second threshold. Identifying whether an iframe is the LCP element requires checking the PerformanceObserver LCP entry, which reports the element type and URL.
Does the browser’s viewport distance threshold for native lazy loading vary across Chrome versions?
Yes. Chrome has adjusted the distance-from-viewport threshold at which it begins fetching lazy-loaded images across multiple releases. Earlier versions used a more conservative threshold, while newer versions fetch earlier on fast connections. This means the same lazy-loading implementation can produce different LCP results depending on Chrome version distribution in field data, making RUM monitoring essential for tracking threshold behavior changes.
Sources
- https://web.dev/articles/optimize-lcp
- https://gtmetrix.com/dont-lazy-load-lcp-image.html
- https://calendar.perfplanet.com/2022/lazy-loading-lcp-images-why-does-this-anti-pattern-happen/
- https://oddjar.com/wordpress-lazy-loading-fix-core-web-vitals-lcp/
- https://www.debugbear.com/blog/lcp-resource-load-delay
- https://www.stanventures.com/news/google-warns-lazy-loading-above-the-fold-images-can-hurt-lcp-4118/