⚡ Core Web Vitals

LCP Image Optimization:
How to Fix Largest Contentful Paint

LCP is the Core Web Vital that most directly impacts your Google ranking — and a slow hero image is the #1 cause of a failing score. This guide covers every technique to get your LCP under 2.5 seconds: fetchpriority, preload, format conversion, responsive sizing, and CDN delivery.

By IMGVO Team
Updated June 2026
14 min read
~3,200 words
2.5s
Google's threshold for a "Good" LCP score
~70%
Of pages have an image as their LCP element (Chrome UX Report)
+32%
Avg. conversion increase reported after hitting "Good" LCP

1. What Is LCP and Why Does It Matter?

Largest Contentful Paint (LCP) measures how long it takes for the largest visible element above the fold to fully render. For roughly 70% of web pages, that element is a hero image — a banner, product photo, or full-width background image near the top of the page.

LCP is one of Google's three Core Web Vitals, which directly affect your search rankings since the 2021 Page Experience update. A poor LCP score doesn't just hurt performance — it reduces your ranking potential and increases bounce rate.

LCP Score Thresholds

Good Needs Improvement Poor
0 – 2.5s 2.5s – 4.0s > 4.0s
💡 Key Distinction

LCP is a real-user metric. Google measures it across all your actual visitors in the Chrome User Experience Report (CrUX). Lab tools like Lighthouse give you a lab score; what counts for ranking is your field data — the 75th percentile of real user experiences.

What Elements Can Be the LCP?

This guide focuses on the most impactful case: optimizing an <img> LCP element.


2. How to Identify Your LCP Element

Before you can optimize your LCP image, you need to know exactly which element it is.

Using Chrome DevTools

  1. Open Chrome DevTools (F12 or Cmd+Option+I)
  2. Go to the Performance tab
  3. Click Record, then reload the page, then stop recording
  4. In the timeline, find the LCP marker — click it to see the element highlighted

Using PageSpeed Insights or Lighthouse

Run PageSpeed Insights on your URL at pagespeed.web.dev. The "Largest Contentful Paint" section shows a screenshot of the LCP element alongside the timing breakdown.

Using Web Vitals JS Snippet

JavaScript
// Log LCP element and timing in the browser console
new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const last = entries[entries.length - 1];
  console.log('LCP element:', last.element);
  console.log('LCP time:', last.startTime.toFixed(0) + 'ms');
}).observe({ type: 'largest-contentful-paint', buffered: true });
💡 Tip — Mobile vs Desktop

Your LCP element may differ between mobile and desktop layouts. If your hero image is hidden on mobile and replaced by a text heading, you have two different LCP elements to optimize. Always test both viewports.


3. Fix #1 — Add fetchpriority="high"

This is the single highest-impact, lowest-effort change you can make. The fetchpriority attribute tells the browser to fetch this image at the highest priority, jumping it to the front of the download queue.

HTML
<!-- Before: normal priority, competes with CSS, fonts, scripts -->
<img
  src="hero.webp"
  alt="Hero image"
  width="1200"
  height="600"
/>

<!-- After: browser fetches this image first -->
<img
  src="hero.webp"
  alt="Hero image"
  width="1200"
  height="600"
  fetchpriority="high"
/>
✓ Google's Own Data

Google's research shows fetchpriority="high" reduces LCP by 20–30ms on average on fast connections, and significantly more on slower mobile connections where bandwidth contention is severe. It's supported in all modern browsers since 2022.

⚠ Only Use on One Image

Only add fetchpriority="high" to your single LCP image. If you apply it to multiple images, the browser treats them all as normal priority again and you lose the benefit entirely.

Browser Support

fetchpriority is supported in Chrome 101+, Edge 101+, Safari 17.2+, and Firefox 132+. Browsers that don't support it simply ignore the attribute — there's no downside to adding it now.


4. Fix #2 — Preload the LCP Image

By default, the browser discovers your LCP image only after parsing the HTML and starting to render — which can be hundreds of milliseconds after the page starts loading. A <link rel="preload"> in the <head> tells the browser to start fetching the image immediately, before it reaches the <img> tag in the body.

Basic Preload

HTML
<head>
  <!-- Preload the LCP image as early as possible in <head> -->
  <link
    rel="preload"
    as="image"
    href="hero.webp"
    fetchpriority="high"
  />
</head>

Preload with Responsive Images (imagesrcset)

If your LCP image is responsive (uses srcset), you must also use imagesrcset and imagesizes on the preload link — otherwise the browser preloads the wrong image size.

HTML
<!-- Preload matches the responsive srcset of the <img> below -->
<link
  rel="preload"
  as="image"
  imagesrcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
  imagesizes="(max-width: 768px) 100vw, 1200px"
  fetchpriority="high"
/>

<!-- The matching <img> in the body -->
<img
  src="hero-1200.webp"
  srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
  sizes="(max-width: 768px) 100vw, 1200px"
  alt="Hero banner showing image compression tool"
  width="1200"
  height="600"
  fetchpriority="high"
/>
💡 Placement Matters

Put your <link rel="preload"> as high in <head> as possible — ideally before any stylesheets or scripts. Every element above it delays discovery of the preload hint.


5. Fix #3 — Never Lazy Load Your LCP Image

loading="lazy" tells the browser to defer fetching an image until it's near the viewport. Applied to your LCP image — which is already in the viewport — this is catastrophic. You're explicitly telling the browser to delay the image that Google is measuring.

HTML
<!-- ✗ NEVER do this to your LCP image -->
<img
  src="hero.webp"
  loading="lazy"   <!-- kills your LCP score -->
  alt="Hero image"
/>

<!-- ✓ Correct: eager (default) + fetchpriority -->
<img
  src="hero.webp"
  loading="eager"
  fetchpriority="high"
  alt="Hero image"
/>

This is a surprisingly common mistake, especially on sites that bulk-apply loading="lazy" to all images via a plugin or global CSS. Always audit your above-the-fold images specifically.


6. Fix #4 — Use WebP or AVIF Format

The format of your LCP image has a direct impact on file size, and therefore download time. JPEG and PNG — the legacy formats still used on most websites — are significantly larger than modern alternatives at the same visual quality.

FormatVs. JPEGBrowser SupportBest For
AVIF30–50% smallerChrome, Firefox, Safari 16+Photos, hero images
WebP25–35% smallerAll modern browsersPhotos, illustrations, UI
JPEGBaselineUniversalFallback for older browsers
PNGOften largerUniversalLossless only; avoid for photos

The Right Way: picture Element with Fallback

Use <picture> to serve AVIF to browsers that support it, WebP as secondary, and JPEG as the universal fallback. Every browser only downloads the first format it supports.

HTML
<picture>
  <!-- AVIF: best compression, newest browsers -->
  <source
    type="image/avif"
    srcset="hero-400.avif 400w, hero-800.avif 800w, hero-1200.avif 1200w"
    sizes="(max-width: 768px) 100vw, 1200px"
  />
  <!-- WebP: great compression, all modern browsers -->
  <source
    type="image/webp"
    srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
    sizes="(max-width: 768px) 100vw, 1200px"
  />
  <!-- JPEG fallback: older browsers -->
  <img
    src="hero-1200.jpg"
    srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
    sizes="(max-width: 768px) 100vw, 1200px"
    alt="Hero banner showing image optimization dashboard"
    width="1200"
    height="600"
    fetchpriority="high"
  />
</picture>
💡 Convert Your Images

IMGVO converts JPEG and PNG to WebP and AVIF directly in your browser — free, no upload, no account needed. Use it to generate all the format variants for your LCP image before deploying.


7. Fix #5 — Serve Correctly Sized Images

Serving an image larger than its rendered size is wasted bandwidth — the browser downloads extra pixels it immediately discards. A 3000px-wide hero image displayed at 1200px wastes roughly 6× the bandwidth it should.

Always Include width and height Attributes

Including explicit width and height on your <img> tag lets the browser reserve space for the image before it loads, preventing Cumulative Layout Shift (CLS) — another Core Web Vital. It also helps the browser calculate resource priority earlier.

HTML
<!-- ✗ No dimensions: causes layout shift, slows priority calculation -->
<img src="hero.webp" alt="Hero" />

<!-- ✓ Correct: width + height preserve aspect ratio, prevent CLS -->
<img
  src="hero.webp"
  alt="Hero banner"
  width="1200"
  height="600"
  fetchpriority="high"
/>

Responsive Image Sizes with srcset

Use srcset with width descriptors to let the browser pick the smallest appropriate image for each viewport:

BreakpointRecommended Max WidthExample File
Mobile (< 480px)480pxhero-480.webp
Tablet (480–768px)768pxhero-768.webp
Laptop (768–1280px)1280pxhero-1280.webp
Desktop (> 1280px)1920px maxhero-1920.webp
💡 The sizes Attribute is Critical

Without a sizes attribute, the browser assumes the image is 100vw and downloads a large variant even if the image is only displayed at 40% of viewport width. Always specify sizes accurately.


8. Fix #6 — Deliver via CDN

A CDN (Content Delivery Network) serves your images from edge servers geographically close to each visitor. For users far from your origin server, this alone can reduce LCP by 300–700ms.

Why CDN Matters for LCP Specifically

What to Look for in a CDN for Images

💡 Quick Win — Cloudflare Free Tier

Cloudflare's free tier acts as a CDN for static assets including images. Simply proxying your domain through Cloudflare typically improves TTFB by 50–200ms for international visitors, with zero code changes.


9. Fix #7 — LCP as CSS Background Image

If your LCP element is a CSS background-image, browser discovery is significantly delayed. The browser must first download and parse the CSS, then apply it, before it knows to fetch the image. This adds 200–500ms compared to a native <img> tag.

Approach 1: Convert to an <img> Tag (Best)

Whenever possible, replace a CSS background hero with a native <img> element. This is the most impactful change — you gain fetchpriority, preload support, srcset, and browser-native optimization.

Approach 2: Preload the Background Image

If you can't change the markup, preload the background image explicitly:

HTML
<!-- Preload the CSS background image in <head> -->
<link
  rel="preload"
  as="image"
  href="hero-bg.webp"
  fetchpriority="high"
/>

<!-- The CSS that uses it -->
/* styles.css */
.hero {
  background-image: url('hero-bg.webp');
}
⚠ Responsive Background Images

CSS background-image with image-set() is still not preloadable with full responsive hints in all browsers. If your background image varies by breakpoint, this is another strong reason to migrate to a native <img> with srcset.


10. Full LCP Image Optimization Checklist


11. Frequently Asked Questions

Convert Your LCP Image to WebP or AVIF — Free

Shrink your LCP hero image by 30–50% instantly. No upload, no account — convert and download directly in your browser.

Convert Images Free →

Related Guides

More resources to help you optimize images for performance and Core Web Vitals.