How to Reduce LCP Below 2.5s with Image Optimization
Your LCP element is probably an image. Here's how to find it, optimize it, and get your Largest Contentful Paint under Google's 2.5-second threshold.
Your LCP is probably an image
Largest Contentful Paint measures how long it takes for the biggest visible element on your page to finish rendering. On most websites, that element is an image — a hero banner, a product photo, or a background image.
Google considers LCP "good" at under 2.5 seconds, "needs improvement" at 2.5-4 seconds, and "poor" above 4 seconds. As of 2026, about 34% of websites fail this threshold, and images are the primary cause.
The good news: image optimization is the highest-leverage fix you can make. A single well-optimized hero image can shave 1-3 seconds off your LCP.
Step 1: Find your LCP element
Before optimizing anything, you need to know which element is actually your LCP. Don't guess.
Using Chrome DevTools:
- Open DevTools (F12)
- Go to the Performance tab
- Click the record button, reload the page, then stop recording
- Look for the "LCP" marker in the timeline — it highlights the exact element
For detailed guidance on using Chrome DevTools for performance analysis, see the official Chrome documentation.
Using PageSpeed Insights: Enter your URL at pagespeed.web.dev. Scroll to the "Diagnostics" section and find "Largest Contentful Paint element." It tells you exactly what it is.
In most cases, it's one of these: a hero/banner image, a product featured image, a background image set via CSS, or a large text block (less common).
Check both mobile and desktop — your LCP element might be different on each. Mobile typically has a worse LCP because of slower connections and smaller caches.
Step 2: Optimize the LCP image itself
Once you know which image is the LCP element, optimize it aggressively.
Compress it
Convert to WebP at quality 75-85. This alone reduces file size by 25-34% compared to JPEG, with no visible quality difference.
For a typical hero image (1200×600), you should be targeting under 100KB. If your hero image is over 200KB, there's room to improve.
Resize it
Serve exactly the dimensions you need. If your hero displays at 1200px wide on desktop and 400px on mobile, don't serve a 3000px original to everyone.
<img
src="/hero-1200.webp"
srcset="/hero-400.webp 400w, /hero-800.webp 800w, /hero-1200.webp 1200w"
sizes="(max-width: 480px) 400px, (max-width: 1024px) 800px, 1200px"
alt="Hero"
width="1200"
height="600"
loading="eager"
fetchpriority="high"
/>
Step 3: Deliver it faster
Even a perfectly compressed image can have slow LCP if the delivery is slow.
Preload the LCP image
Add this to your <head>. It tells the browser to start downloading the image immediately, before it even parses the CSS:
<link
rel="preload"
as="image"
href="/hero-1200.webp"
fetchpriority="high"
type="image/webp"
/>
Avoid CSS background images for LCP
If your LCP element is set via background-image in CSS, the browser can't discover it until the CSS is parsed and applied. Move it to an <img> tag with fetchpriority="high" instead.
Use a CDN
Serving images from a CDN reduces latency by serving from the closest geographic location. Most hosting providers (Vercel, Cloudflare, Netlify) include CDN by default.
Enable compression
Make sure your server sends images with proper compression headers:
Content-Encoding: br (Brotli, preferred)
Content-Encoding: gzip (fallback)
Cache-Control: public, max-age=31536000, immutable
The immutable cache directive tells browsers the file won't change, avoiding unnecessary revalidation requests.
Step 4: Don't block the render
Your image loads fast, but other resources might be blocking it.
Defer non-critical JavaScript
Every render-blocking script delays your LCP. Move non-critical scripts to defer or async:
<!-- Render-blocking (bad for LCP) -->
<script src="/analytics.js"></script>
<!-- Non-blocking (good for LCP) -->
<script src="/analytics.js" defer></script>
Inline critical CSS
If your above-the-fold styles are in an external stylesheet, the browser has to download and parse it before rendering anything. Inline the critical CSS for the hero section directly in <style> tags.
Common mistakes that kill LCP
Lazy loading the LCP image. The loading="lazy" attribute tells the browser to deprioritize the image. Never use it on your LCP element. Use loading="eager" instead (or omit the attribute entirely, since eager is the default).
Using a carousel/slider as the hero. Carousels often load JavaScript before rendering the first image, adding unnecessary delay. A static hero image with good compression will always be faster.
Serving from a different origin. If your image is on images.example.com but your page is on example.com, the browser needs an additional DNS lookup and TLS handshake. Use the same origin or preconnect:
<link rel="preconnect" href="https://images.example.com" />
Measuring improvement
After making changes, test again:
- Run PageSpeed Insights 3 times and average the results (lab scores vary between runs)
- Check the Chrome UX Report data in Search Console (this is real user data, and what Google actually uses for rankings)
- Monitor over 28 days — CrUX data is based on a rolling 28-day window
For more details on LCP thresholds and measurement techniques, see Google's LCP documentation.
Target: LCP under 2.5s on mobile with a slow 3G connection. If you hit that, you're in good shape for any connection speed.
Compress your LCP image now
Convert to WebP and resize in seconds — free, in your browser, no uploads.