On most stores we audit, images are 60–80% of page weight and the direct cause of slow LCP. The optimization pipeline is well understood — the gap is that most sites apply pieces of it in the wrong order. Here is the full pipeline, from upload policy to the LCP special case.
Step 1: Choose formats by generation, not by plugin
- WebP for everything: 25–35% smaller than JPEG at equivalent quality. Universal browser support since 2020.
- AVIF where available: another 10–20% smaller, support now broad — the comparison numbers in the optimizer test show plugin-level AVIF differences.
- PNG only for logos and graphics with transparency; JPEG is dead as an upload format.
Step 2: Enforce an upload policy
The best compression is not uploading bloat. Our policy: images exported at display size (a 800px-wide slot gets a ≤800px file, not a 4000px original downscaled by CSS), quality 80 for photography. Media-library discipline compounds with every plugin — the library audits in the cleanup test apply to attachments too.
Step 3: Let WordPress generate responsive sizes
The srcset mechanism serves each device an appropriately sized file — free performance built into WordPress since 4.4, as long as your theme outputs the_post_thumbnail() correctly and you do not hotlink full-size originals in content.
Step 4: Lazy-load everything — except the LCP image
Native lazy loading (loading="lazy") is automatic in modern WordPress and covers most images. The critical exception: the LCP image must load eagerly, ideally with fetchpriority="high". Lazy-loading the hero delays the very metric that judges your site — the measured wound in the lazy-loading comparison.
Step 5: Fix CLS while you are in there
Every <img> needs width and height attributes (WordPress adds them automatically from the attachment metadata) so the browser reserves space. CSS background-image heroes are the recurring CLS/LCP offender — replace them with real <img> elements, per the patterns in the CWV guide.
Step 6: Delivery
Serve images from the same fast path as the page: the page cache does not apply to static files, but browser cache and CDN do — long TTLs on images are safe (filenames change when content changes). The CDN decision logic: the CDN comparison.
The pipeline, summarized
Upload right-sized WebP → WordPress generates responsive variants → lazy-load below the fold → eager + preload the LCP image → dimensions everywhere → CDN delivery. Sites that follow all six sit comfortably under LCP thresholds; sites that skip step 4’s exception routinely fail it. The free audit checks your images against this exact pipeline.
WebP everywhere, AVIF where your stack generates it — both dramatically smaller than JPEG. PNG only for transparency graphics. JPEG as an upload format is obsolete. It is probably the LCP element being lazy-loaded, or shipped oversized. Eager-load it with fetchpriority=high, size it to its container, and serve WebP. For below-the-fold images, yes — it defers bytes the visitor may never scroll to. But lazy-loading the LCP image worsens the metric that matters; keep that one eager. Width and height attributes on every img tag so browsers reserve space before loading — WordPress adds these automatically from attachment metadata when you use standard template functions.What image format should WordPress use?
Why is my hero image slowing down my site?
Does lazy loading improve WordPress speed?
How do I stop images causing layout shift?