Lazy Loading Images: The One-Line Fix That Backfires on LCP
loading="lazy" on every image is one of the most common LCP killers. Here's why it happens and how to apply lazy loading correctly.
Adding loading="lazy" to every image on a page looks like an easy performance win. In practice, applying it uniformly — including to hero banners and other above-the-fold visuals — usually makes the page feel slower. The browser delays fetching the image until it's near the viewport, but if that image is already in the viewport on load, you've just delayed your LCP element for no reason.
What loading="lazy" Actually Does
Native lazy loading tells the browser not to fetch an image until it's within a certain distance from the viewport (typically 1000–1500px on fast connections, less on slow connections). This is beneficial for images that are off-screen on load — it reduces initial page weight and speeds up critical resource loading.
The LCP Trap
LCP measures when the largest visible element becomes painted. If that element is an image with loading="lazy", the browser defers its fetch until after initial parsing, JavaScript execution, and layout — adding 200–800ms of avoidable delay on a typical page load. Google's own documentation flags this as a common mistake.
Never add loading="lazy" to your LCP image. PageSpeed Insights will flag this directly. The hero banner, above-fold product photo, or any image visible on initial load should use loading="eager" (or omit the attribute — eager is the default).
<!-- ✅ Correct: LCP image loads immediately -->
<img
src="hero.webp"
alt="Product hero"
width="1200"
height="630"
fetchpriority="high"
decoding="async"
>
<!-- No loading attribute = eager by default -->
<!-- ✅ Correct: below-fold images lazy load -->
<img
src="product-2.webp"
alt="Product detail"
width="600"
height="600"
loading="lazy"
decoding="async"
>
<!-- ❌ Wrong: LCP image deferred -->
<img src="hero.webp" loading="lazy" alt="Hero">The fetchpriority Attribute
fetchpriority="high" tells the browser's resource scheduler to prioritise this image over other resources at the same network priority. Use it on your LCP image — it's one of the most effective single-attribute LCP improvements available.
| Image position | loading | fetchpriority | decoding | Why |
|---|---|---|---|---|
| LCP / hero (above fold) | eager (default) | high | async | Fetch immediately; scheduler prioritises above other resources |
| Above fold, not LCP | eager (default) | auto (default) | async | Load normally; don't delay with lazy |
| Just below fold (1st scroll) | eager (default) | auto (default) | async | Preload scanner discovers early enough |
| Well below fold | lazy | auto (default) | async | Defer until user scrolls near; reduces initial payload |
| Hidden tabs / carousel | lazy | low | async | May never be seen; lowest priority |
Correct Lazy Loading Strategy
- ●Above the fold: No
loadingattribute (eager default) +fetchpriority="high"on LCP image - ●Second viewport (partially visible on scroll): No
loadingattribute — let the browser preload scanner discover naturally - ●Below the fold:
loading="lazy"— definite win - ●In carousels/tabs not visible on load:
loading="lazy"
Even with perfect lazy loading, an oversized or poorly compressed LCP image will still fail Core Web Vitals. Compress your hero image first — then verify with PageSpeed Insights that lazy loading is correctly applied to only below-fold images.
Ready to try it?
All tools run entirely in your browser — no uploads, no account required.
Compress Image