Why the product image is almost always the LCP element
Largest Contentful Paint measures when the biggest visible element in the viewport finishes rendering. On a product detail page, that element is nearly always the hero product image. It is the largest thing above the fold by design — shoppers came to look at the product, so the image gets the most pixels.
This has an awkward consequence: the single asset your conversion rate depends on most is also the single asset your Core Web Vitals score depends on most. You cannot shrink it into compliance without hurting the thing it exists to do. A blurry, over-compressed hero passes the audit and loses the sale.
The numbers say most stores have not solved this. Roughly 43% of e-commerce sites fail the LCP threshold on mobile, and only about 57% pass all three Core Web Vitals on mobile. Product pages are where those failures concentrate.
One detail trips people up constantly: Google scores you at the 75th percentile of real user visits, not the average and not your lab test. Your desktop test on office fibre is not the measurement. A quarter of your shoppers can be slower than your target and you still pass; if more than a quarter are slower, you fail no matter how good your median looks.
Stop guessing: break LCP into its four subparts
The most useful change in performance guidance recently is the shift to diagnosing LCP by subpart rather than treating it as one number. Every LCP measurement decomposes into four consecutive spans, and they have completely different fixes. Compressing your image only helps one of them.
| Subpart | What it measures | What actually fixes it |
|---|---|---|
| Time to First Byte | Server response before any HTML arrives | Caching, hosting, backend queries |
| Resource Load Delay | Gap between HTML arriving and the browser starting the image download | Discovery: preload, fetchpriority, no lazy-load |
| Resource Load Duration | The actual download of the image bytes | Format, compression, dimensions, CDN |
| Element Render Delay | Image downloaded but not yet painted | Render-blocking CSS/JS, font loading, hydration |
Here is the part that surprises teams: on a typical product page, load delay is frequently larger than download duration. The browser sits idle for hundreds of milliseconds because it has not yet discovered the image — it is buried in a JavaScript-rendered carousel, or referenced only in CSS, or the request is queued behind blocking scripts. You can halve your file size and move LCP by almost nothing, because bytes were never the bottleneck.
Pull the subpart breakdown for your top three product pages before changing a single image. If load delay or render delay dominates, image compression is the wrong project entirely — you have a discovery or a blocking-resource problem, and it is usually cheaper to fix.
Fix discovery first — it is free and it is usually the biggest win
Resource load delay is the cheapest subpart to fix because it requires no new assets, only markup changes. Four rules cover almost all of it.
Never lazy-load the hero. Blanket loading="lazy" across every image is the single most common self-inflicted LCP wound in e-commerce. It is correct for the gallery thumbnails below the fold and actively harmful on the main image. Lazy-load everything except the LCP candidate.
Mark the hero as high priority. Adding fetchpriority="high" to the main product image tells the browser to promote it ahead of the dozens of other requests competing for bandwidth on a product page — analytics, chat widgets, review scripts, recommendation carousels.
Make sure it is in the HTML. If your gallery component renders client-side, the browser's preload scanner cannot see the image URL until JavaScript executes. Server-render the first image, or add an explicit <link rel="preload" as="image"> with matching imagesrcset.
Preconnect to your image host. If images come from a CDN on a different origin, the browser pays for DNS, TCP and TLS before the first byte. A single <link rel="preconnect"> removes that round trip.
Proportions vary by stack, but the shape is consistent: the majority of most product-page LCP budgets is spent not downloading the image. Teams who only ever optimize the 25% slice are fighting for the smallest share.
Then cut the bytes without cutting the quality
Once discovery is clean, download duration is worth attacking — and modern formats make it a large, safe win. AVIF runs roughly 65% smaller than JPEG at equivalent perceived quality; WebP lands around 50% smaller. Serve AVIF with a WebP fallback and a JPEG last resort, and let content negotiation pick per browser.
The second lever is dimensions. Shipping a 3000px master to a 390px-wide phone wastes bandwidth on pixels no one can resolve. A correct srcset with a matching sizes attribute lets the browser request the right variant per breakpoint and per device pixel ratio. On mobile this routinely outperforms any compression tuning, because you are removing whole megapixels rather than shaving quality points.
Common Setup
- One 2500px JPEG for every device
- Quality slider set globally to 60
loading="lazy"on all images- Gallery rendered entirely in JS
- Hero competes with analytics for bandwidth
Subpart-Aware Setup
- AVIF/WebP with srcset per breakpoint
- Quality tuned per image, not globally
- Hero eager; thumbnails lazy
- First image server-rendered or preloaded
fetchpriority="high"on the hero
Resist the urge to solve this with one aggressive global quality setting. Compression artifacts are not evenly distributed across a catalog: flat backgrounds and hard product edges survive heavy compression comfortably, while fabric texture, hair, brushed metal and gradients fall apart. If you want the detail on where that line sits, our guide to compression and quality loss covers it, and the format comparison covers which container to reach for.
Don't fix LCP and break CLS
Layout shift and LCP are easy to trade against each other by accident. The classic failure: an image without declared dimensions loads, the page reflows, everything below it jumps, and the shopper taps "Add to cart" a fraction of a second after it moved.
Always set explicit width and height attributes (or an equivalent CSS aspect-ratio) on every product image, including thumbnails. The browser then reserves the correct box before any bytes arrive, and nothing moves when they do. This costs nothing and is one of the highest-yield two-attribute changes available.
Consistent aspect ratios across the catalog help here for a structural reason. If every image in your gallery is the same shape, one reserved box works for all of them, your grid never reflows as thumbnails resolve, and the layout is stable before a single image has downloaded. Catalogs with mixed portrait and square images are fighting a layout problem that ratio discipline would have prevented.
Blur-up and skeleton placeholders can register as the LCP element themselves if they are large and paint early. That makes your reported LCP look better than the shopper's actual experience of seeing the product. Verify which element the browser is actually attributing before you celebrate a fixed score.
Where the image pipeline itself matters
Most of the advice above is front-end work. But a meaningful share of product-page weight is decided far upstream, at the point images are produced and stored.
Studio-shot catalogs tend to accumulate inconsistency: different crops, different framing distances, different backgrounds shot across different sessions. Each inconsistency forces a workaround downstream — per-image cropping rules, per-template aspect ratios, more variants to generate and cache. Every workaround is another opportunity to ship the wrong-sized file.
Catalogs generated with a consistent pipeline start from a better place. When every image leaves production at the same dimensions, the same framing and the same background treatment, responsive variants become mechanical: one ratio, one srcset ladder, one set of reserved boxes. Retouchable produces catalog images on a fixed spec by default, which removes the class of performance problems that come from images being subtly different from one another rather than from being too large.
Whatever the source, the storage and delivery layer matters just as much — origin images should be masters, and every public variant should be derived and cached at the edge. Our CDN setup guide covers that architecture, and image loading speed and SEO covers the ranking side of the equation.
A practical audit order
Performance work goes badly when it is done in the wrong order, because early wins get masked by later bottlenecks. This sequence surfaces the biggest problems first and avoids wasted effort.
| Step | Action | Typical impact |
|---|---|---|
| 1 | Pull field data at the 75th percentile, mobile only | Establishes the real baseline |
| 2 | Break LCP into its four subparts on top PDPs | Tells you which fix matters |
| 3 | Remove lazy-load from the hero; add fetchpriority | Large, near-zero cost |
| 4 | Server-render or preload the first gallery image | Large on JS-heavy themes |
| 5 | Add width/height to every image | Fixes CLS outright |
| 6 | Ship AVIF/WebP with a correct srcset ladder | Moderate to large on mobile |
| 7 | Defer third-party scripts competing with the hero | Cuts render delay |
| 8 | Re-measure after four weeks of field data | Confirms the change is real |
Step 8 is the one most often skipped. Core Web Vitals are reported on a rolling 28-day window of real user data, so a fix deployed today will not show fully for weeks. Teams who re-check after two days conclude the work did nothing and revert it. Set the expectation before you start, and measure lab data for immediate feedback while you wait for the field numbers to catch up.
Finally, keep the goal straight. The point of passing Core Web Vitals is not the score — it is that a shopper on a mid-range phone on a mediocre connection sees your product clearly and quickly. Every decision above should be tested against that, not against a dashboard colour.