Fix Large Images for Better LCP

Optimize LCP images with responsive srcset, modern formats like WebP and AVIF, and proper compression. Reduce image size without losing quality.
Harlan WiltonHarlan Wilton7 min read Published

73% of mobile pages have an image as their LCP element. When that image is unoptimized, nothing else you do matters—you're bottlenecked by download time.

The median site keeps LCP images under 100KB, but 8% of sites serve LCP images over 1MB. That's 5-10 seconds of download time on 3G.

What's the Problem?

Large images slow LCP in a direct, linear way: bigger file = longer download. The resource load duration—how long the image takes to download—accounts for roughly 40% of typical LCP time.

Common causes:

  • Using JPEG or PNG instead of WebP/AVIF (2-3x larger)
  • Serving desktop-sized images to mobile devices
  • No compression or using maximum quality
  • Ignoring responsive images (srcset/sizes)
  • Animated GIFs instead of video formats

Lighthouse flags this through multiple audits: "Properly size images," "Serve images in next-gen formats," "Efficiently encode images," and the combined "Improve image delivery" insight.

The Math

A 1MB hero image on a 3G connection (1.5 Mbps):

  • Download time: ~5.3 seconds
  • Your LCP cannot be faster than 5.3 seconds

The same image optimized to 100KB:

  • Download time: ~530ms
  • LCP budget now available for other things

How to Identify This Issue

Chrome DevTools

  1. Open Network tab (F12)
  2. Filter by "Img"
  3. Find your LCP image (usually the largest above-fold image)
  4. Check the "Size" column
  5. Click the image, check "Content-Length" in headers

Red flags:

  • LCP image > 200KB on desktop
  • LCP image > 100KB on mobile
  • Download time > 500ms on good connection

Lighthouse

Look for these audits:

  • "Properly size images" — Image dimensions vs display size
  • "Serve images in next-gen formats" — JPEG/PNG that should be WebP/AVIF
  • "Efficiently encode images" — Compression opportunities
  • "Improve image delivery" — Combined recommendations

WebPageTest

Waterfall chart shows exact download time per image. Look for long bars on image requests.

The Fix

1. Use Modern Image Formats

WebP and AVIF are 30-50% smaller than JPEG at equivalent visual quality.

<!-- Before: JPEG only -->
<img src="hero.jpg" alt="Hero">

<!-- After: modern formats with fallback -->
<picture>
  <source srcset="hero.avif" type="image/avif">
  <source srcset="hero.webp" type="image/webp">
  <img src="hero.jpg" alt="Hero" width="1200" height="600">
</picture>

Format comparison at ~80 quality:

FormatTypical sizeBrowser support
JPEG150KB100%
WebP90KB97%+
AVIF60KB93%+

Use AVIF as primary, WebP as fallback, JPEG for ancient browsers.

2. Use Responsive Images

Don't serve 2400px images to 400px mobile screens.

<img
  src="hero.webp"
  srcset="
    hero-400.webp 400w,
    hero-800.webp 800w,
    hero-1200.webp 1200w,
    hero-1600.webp 1600w
  "
  sizes="100vw"
  width="1200"
  height="600"
  alt="Hero"
>

Understanding srcset and sizes:

  • srcset lists available images with their widths (400w = 400px wide)
  • sizes tells browser how wide the image will display
  • Browser picks the optimal image based on screen size and DPR

Common sizes patterns:

<!-- Full width hero -->
sizes="100vw"

<!-- Full width mobile, half width desktop -->
sizes="(max-width: 768px) 100vw, 50vw"

<!-- Fixed width sidebar image -->
sizes="300px"

<!-- Complex layout -->
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"

3. Compress Appropriately

Quality 80-85 is visually indistinguishable from 100 for most images.

npx sharp-cli hero.jpg -o hero.webp -- webp -q 80

convert hero.jpg -quality 80 hero.webp

# cwebp (Google)
cwebp -q 80 hero.jpg -o hero.webp

Quality guidelines:

Image typeQualityRationale
Hero/LCP80-85Needs to look sharp
Product photos75-80Balance quality/size
Thumbnails70-75Small display size
Backgrounds60-70Often blurred/dimmed

4. Set Explicit Dimensions

Always include width and height to prevent layout shifts and help browser allocate space.

<img
  src="hero.webp"
  width="1200"
  height="600"
  style="width: 100%; height: auto;"
  alt="Hero"
>

Or use CSS aspect-ratio:

.hero-img {
  width: 100%;
  aspect-ratio: 2 / 1;
  object-fit: cover;
}

5. Use an Image CDN

Image CDNs (Cloudinary, imgix, Cloudflare Images) handle format selection, resizing, and compression automatically.

<!-- Cloudinary: automatic format, width, quality -->
<img
  src="https://res.cloudinary.com/demo/image/upload/w_800,q_auto,f_auto/hero.jpg"
  srcset="
    https://res.cloudinary.com/demo/image/upload/w_400,q_auto,f_auto/hero.jpg 400w,
    https://res.cloudinary.com/demo/image/upload/w_800,q_auto,f_auto/hero.jpg 800w,
    https://res.cloudinary.com/demo/image/upload/w_1200,q_auto,f_auto/hero.jpg 1200w
  "
  sizes="100vw"
  alt="Hero"
>

Benefits:

  • Automatic WebP/AVIF serving
  • Dynamic resizing
  • Global CDN caching
  • No build-time image generation

Complete Example

<picture>
  <!-- AVIF for modern browsers -->
  <source
    type="image/avif"
    srcset="
      hero-400.avif 400w,
      hero-800.avif 800w,
      hero-1200.avif 1200w
    "
    sizes="100vw"
  >
  <!-- WebP fallback -->
  <source
    type="image/webp"
    srcset="
      hero-400.webp 400w,
      hero-800.webp 800w,
      hero-1200.webp 1200w
    "
    sizes="100vw"
  >
  <!-- JPEG for old browsers -->
  <img
    src="hero-800.jpg"
    srcset="
      hero-400.jpg 400w,
      hero-800.jpg 800w,
      hero-1200.jpg 1200w
    "
    sizes="100vw"
    width="1200"
    height="600"
    fetchpriority="high"
    decoding="async"
    alt="Descriptive alt text"
  >
</picture>

Why This Works

Image download time is governed by simple physics: file size divided by bandwidth. You cannot make bytes download faster—you can only send fewer bytes.

Modern formats use better compression algorithms:

  • WebP: Predictive coding, superior entropy encoding
  • AVIF: AV1 video codec applied to images, excellent for photos

Responsive images ensure you're not sending 4x more pixels than needed:

  • 2400px image at 2x DPR for 600px display = 4.8 megapixels
  • 1200px image at 2x DPR for 600px display = 1.2 megapixels
  • That's 75% fewer pixels to compress

Combined, format + responsive + compression can reduce image size by 80-90%.

Framework-Specific Solutions

Next.jsnext/image handles everything—format selection, responsive sizes, lazy loading:
import Image from 'next/image'

<Image
  src="/hero.jpg"
  width={1200}
  height={600}
  priority // For LCP image
  sizes="100vw"
  alt="Hero"
/>
Configure quality in next.config.js:
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920],
    quality: 80,
  },
}
NuxtUse @nuxt/image with a provider (ipx, cloudinary, etc.):
<NuxtImg
  src="/hero.jpg"
  width="1200"
  height="600"
  sizes="100vw sm:100vw md:100vw lg:100vw"
  format="webp"
  quality="80"
  preload
  alt="Hero"
/>
Configure in nuxt.config.ts:
export default defineNuxtConfig({
  image: {
    quality: 80,
    format: ['webp', 'avif'],
    screens: {
      sm: 640,
      md: 768,
      lg: 1024,
      xl: 1280,
    },
  },
})
ReactNo built-in solution. Use an image component library or build your own:
function ResponsiveImage({ src, alt, sizes = '100vw' }) {
  const base = src.replace(/\.[^.]+$/, '')
  const ext = src.match(/\.[^.]+$/)?.[0] || '.jpg'

  return (
    <picture>
      <source
        type="image/avif"
        srcSet={`${base}-400.avif 400w, ${base}-800.avif 800w, ${base}-1200.avif 1200w`}
        sizes={sizes}
      />
      <source
        type="image/webp"
        srcSet={`${base}-400.webp 400w, ${base}-800.webp 800w, ${base}-1200.webp 1200w`}
        sizes={sizes}
      />
      <img
        src={`${base}-800${ext}`}
        srcSet={`${base}-400${ext} 400w, ${base}-800${ext} 800w, ${base}-1200${ext} 1200w`}
        sizes={sizes}
        alt={alt}
        fetchPriority="high"
      />
    </picture>
  )
}
Or use an image CDN and construct URLs dynamically.

Verify the Fix

After implementing:

  1. Network tab — Check new file sizes, should be significantly smaller
  2. Response headers — Verify Content-Type shows webp or avif
  3. Lighthouse — Image audits should pass or show smaller potential savings
  4. Compare LCP — Before/after measurement

Expected improvement: Reducing a 500KB JPEG to 100KB WebP can save 400-800ms on typical connections.

Common Mistakes

Wrong sizes Attribute

If sizes doesn't match actual layout, browser downloads wrong image.

<!-- Wrong: says full width, but image is actually half width -->
<img sizes="100vw" src="..." style="width: 50%">

<!-- Right: matches layout -->
<img sizes="50vw" src="..." style="width: 50%">

Over-Compressing

Quality too low creates visible artifacts. Test visually.

cwebp -q 30 hero.jpg -o hero.webp  # Will look bad

cwebp -q 80 hero.jpg -o hero.webp

Forgetting High-DPR Displays

2x and 3x displays need larger source images.

<!-- srcset should include sizes for high-DPR -->
srcset="
  hero-400.webp 400w,   /* 400px @ 1x */
  hero-800.webp 800w,   /* 400px @ 2x, 800px @ 1x */
  hero-1200.webp 1200w  /* 400px @ 3x, 600px @ 2x */
"

Only Optimizing Desktop

Mobile users on slow networks benefit most from image optimization. Test on mobile.

Often appears alongside:

Test Your Entire Site

Image optimization varies by page. Your homepage hero might be perfect while blog post images are unoptimized PNGs. Unlighthouse scans your entire site and identifies pages with oversized images.