Images Are Slowing Largest Contentful Paint
An image can be the LCP element without being the root cause. Break the event into server response, resource discovery, download, decode, and render delay before changing formats.
Diagnostic matrix
| Evidence | Likely bottleneck | Fix first |
|---|---|---|
| Request starts late | Discovery | Initial HTML, preload/prioritization, remove lazy loading |
| Request starts early but lasts long | Bytes/network | Right-size and encode the selected candidate |
| Download ends but LCP waits | Decode/render/main thread | Inspect dimensions, CSS, scripts, and rendering |
| Wrong candidate loads |
sizes or layout |
Correct responsive markup |
| TTFB dominates | Server/document | Fix response path before image tuning |
Investigation workflow
- Measure field data when available and reproduce with a representative mobile profile.
- Identify the actual LCP element; it can change by viewport.
- Inspect its request start, response end, and paint time.
- Confirm it is discoverable in HTML and not lazy-loaded.
- Compare rendered dimensions with the selected resource.
- Check cache policy, CDN behavior, redirects, and server timing.
- Re-test after one change.
Image fixes that matter
Provide intrinsic dimensions, accurate srcset/sizes, an efficient format supported by the target browsers, and sufficient quality at the rendered size. Use JPG to WebP or PNG to AVIF only after confirming that encoding is the bottleneck. A smaller format cannot repair late discovery.
Discovery delay versus resource delay
If the request begins late, reducing bytes attacks the wrong interval. Check whether client-side rendering, CSS backgrounds, injected markup, or delayed hydration hides the URL from the preload scanner. Put a genuine content image in initial HTML when practical. If the request begins promptly but completes slowly, inspect candidate size, cache status, server response, and delivery distance.
Decode and render delay
A completed request can still wait to paint. Very large intrinsic dimensions raise decode work; main-thread JavaScript, overlays, and entrance animations can delay rendering. Temporarily substitute a small known-good image without changing layout. If paint remains late, the bottleneck is probably outside the encoded asset.
Production verification
Test direct navigation, repeat navigation, and a cold mobile load. Record the selected candidate, transfer bytes, request priority, cache result, and timing breakdown. Confirm improvements across several runs and monitor field data after release.
Common mistakes
- Lazy-loading the hero.
- Preloading one URL while
srcsetselects another. - Serving a 3000-pixel asset into a 600-pixel slot.
- Optimizing a logo when a background image is the actual LCP.
- Using lab score changes without checking field users.
Prioritization framework
Fix the largest measured interval. For late discovery, expose the URL and remove lazy loading. For transfer delay, correct candidate sizing, encoding, caching, and delivery. For render delay, reduce main-thread and visibility blockers. For high server response time, fix document delivery first.
Before-and-after evidence
Keep page, viewport, throttling, and cache state constant. Save the waterfall and LCP subparts before and after. Confirm that the selected resource changed as intended and quality remains acceptable. A score change caused by different test conditions is not evidence.