Fix Large Images for Better LCP
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
- Open Network tab (F12)
- Filter by "Img"
- Find your LCP image (usually the largest above-fold image)
- Check the "Size" column
- 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:
| Format | Typical size | Browser support |
|---|---|---|
| JPEG | 150KB | 100% |
| WebP | 90KB | 97%+ |
| AVIF | 60KB | 93%+ |
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:
srcsetlists available images with their widths (400w= 400px wide)sizestells 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 type | Quality | Rationale |
|---|---|---|
| Hero/LCP | 80-85 | Needs to look sharp |
| Product photos | 75-80 | Balance quality/size |
| Thumbnails | 70-75 | Small display size |
| Backgrounds | 60-70 | Often 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/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"
/>
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920],
quality: 80,
},
}
@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"
/>
export default defineNuxtConfig({
image: {
quality: 80,
format: ['webp', 'avif'],
screens: {
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
},
},
})
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>
)
}
Verify the Fix
After implementing:
- Network tab — Check new file sizes, should be significantly smaller
- Response headers — Verify Content-Type shows webp or avif
- Lighthouse — Image audits should pass or show smaller potential savings
- 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.
Related Issues
Often appears alongside:
- Prioritize LCP Image — Optimized image + priority = fast LCP
- LCP Lazy Loaded — Don't lazy-load your optimized hero
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.