Images are usually the heaviest resource on any page, and at the same time the one that's worst optimized by default: uploading a 4000×3000 pixel photo straight from a camera or phone into a CMS, with no resizing or compression, is the single most common cause of a high LCP. The good news is that, unlike other technical problems, image optimization has concrete, measurable fixes, not opinion-based tweaks.
Formats: when to use WebP, AVIF or stick with JPEG/PNG
WebP delivers a 25-35% weight reduction over JPEG at equivalent visual quality, and has practically universal support in modern browsers, making it a reasonable default for most projects today. AVIF compresses even better (up to 50% less than JPEG in some cases) but requires more CPU time to encode the first time, which matters when generating thousands of variants automatically; its browser support is broad but somewhat more recent than WebP's. PNG is still needed when real transparency is required without lossy compression's limits, such as logos or icons with defined edges, and SVG is always superior to any pixel-based format for vector icons and logos, since it scales without losing sharpness and weighs a fraction of what the same rasterized image would.
srcset and sizes: serving the right size to each screen
A widespread mistake is serving the same image, at the same file size, to both a 375-pixel-wide phone and a 2560-pixel desktop monitor. The srcset attribute lets you declare several versions of the same image at different widths, and sizes tells the browser how wide it will actually be at each breakpoint, so it downloads only the version it needs:
<img
src="product-800.webp"
srcset="product-400.webp 400w, product-800.webp 800w, product-1600.webp 1600w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
width="800" height="800"
alt="Nordic oak chair">
Without this attribute, a mobile user typically downloads 3 to 6 times more data than their screen can ever show, directly hurting LCP on the very device where it matters most (mobile traffic is usually the majority and the hardware more constrained).
Lazy loading: useful almost always, counterproductive in one specific case
The native loading="lazy" attribute delays downloading an image until it's about to enter the viewport, saving bandwidth on images the user may never scroll to. The mistake that actually matters to avoid is applying it to the LCP candidate image (usually the first visible image, above the fold): deliberately delaying the load of the very image the performance metric is measuring is counterproductive and makes LCP worse instead of better. The practical rule is simple: loading="lazy" on everything except the first visible image on the page, which should use loading="eager" (or simply omit the attribute, which is the default) and, if it's the LCP candidate, also fetchpriority="high".
<!-- First visible image: immediate, prioritized load -->
<img src="hero.webp" fetchpriority="high" width="1200" height="600" alt="...">
<!-- Images further down the page: deferred load -->
<img src="product-2.webp" loading="lazy" width="400" height="400" alt="...">
Compression: visual quality versus file weight
Lossy compression for JPEG or WebP lets you pick a quality level, usually between 0 and 100; in practice, values between 75 and 85 are visually indistinguishable from the original for most photographs, but substantially reduce file weight compared to a quality of 95 or 100, which is rarely justified except in product photography where zoom is a key feature. Over-compressing (below 60) does introduce visible artifacts (blocking, loss of detail in textured areas), so the goal isn't minimizing weight at all costs but finding the point where compressing further stops saving noticeable weight in exchange for visibly worse quality.
Explicit dimensions: the connection to Core Web Vitals
Every image must declare width and height (or its CSS equivalent, aspect-ratio), not just as good practice but because it's the most common and easiest-to-fix cause of a high CLS, as explained in the Core Web Vitals guide: without those dimensions, the browser can't reserve the space the image will occupy before downloading it, and surrounding content shifts when it finishes loading.
Alt text: real SEO, not just accessibility
The alt attribute serves a double function that's rarely fully understood: it describes the image to screen readers for visually impaired users (its primary purpose), and it's practically the only textual context Google has to understand what an image shows and index it in Google Images or associate it with a relevant search. A useful alt describes what's visible concisely and specifically ("nordic oak chair with curved backrest," not "image1" nor, at the other extreme, a paragraph stuffed with keywords unrelated to what the image actually shows, which Google reads as spam).
CDN and caching: why they matter as much as the file itself
Even a perfectly optimized image still depends on network latency to the server serving it. A CDN (content delivery network) replicates images on servers geographically close to the user, reducing that latency; combined with aggressive cache headers (as explained in the HTTP caching and CDN guide), it lets a user's second visit, or another user's visit to the same page, load images almost instantly from an intermediate cache without hitting the origin server again.
Frequently asked questions
Should I convert all my images to WebP at once?
It's recommended for new images and feasible with automated tools for an existing catalog, but it's worth also keeping the original format (JPEG/PNG) as a fallback via the <picture> tag for older browsers that don't support WebP, though today they're a residual minority.
How heavy is "too heavy" for an image?
There's no absolute limit, but as a practical reference: a well-optimized product or blog image in WebP should rarely exceed 150-200 KB, and a background or hero image, 300-400 KB, even at large resolutions.
Does lazy loading hurt SEO?
Not if implemented with the native loading="lazy" attribute, which Google processes correctly during rendering. The historical problems came from older JavaScript-based implementations that hid the real image until a scroll event, which could prevent Google from discovering it.
Is it worth optimizing images if I already use a caching plugin?
Yes, they're independent layers: caching avoids repeating the download on later visits, but every user's first visit (and every crawler) always downloads the real file, so its optimized weight still determines that first load's performance.
Will AVIF replace WebP?
It's likely to gain share over time given its better compression ratio, but today they coexist: many projects serve AVIF with WebP as an automatic fallback (via <picture>) to cover the support gap, rather than picking just one exclusively.