What is Image Optimization?
Image optimization is a set of techniques that reduce image file size and improve page load performance.
What is Image Optimization?
Image optimization is reducing file size and delivering the right format, resolution, and dimensions for each user's device. Images account for 40-60% of a page's total weight (HTTP Archive), making them the biggest culprit in slow load times. Key techniques: lossy and lossless compression, modern formats (WebP, AVIF), responsive srcset delivery, lazy loading below-the-fold content. Google's Largest Contentful Paint (LCP) metric—one of three Core Web Vitals—directly measures how fast the largest visible element (often a hero image) renders. You need 2.5 seconds or less for a "good" score. On projects we've shipped, switching from unoptimized PNGs to properly sized AVIF images cut hero payloads by 70-85%. We routinely hit sub-1.5s LCP on 4G connections.
How it works
Image optimization happens across three layers: format, compression, and delivery.
Format selection
Modern formats encode pixels more efficiently. WebP (released by Google in 2010, broadly supported since ~2020) gives you 25-35% smaller files than JPEG at equivalent quality. AVIF (based on AV1, supported in Chrome since v85 and Safari since 16.0) goes further—typically 30-50% smaller than WebP for photos. For simple graphics and icons, SVG's still the best choice since it's resolution-independent.
Compression
Lossy compression (e.g., quality: 75 in Sharp or Squoosh) throws away data your eye won't miss. Lossless compression removes redundant data without quality loss. Tools like Sharp (the library behind Next.js Image) let you set quality per format:
import sharp from 'sharp';
await sharp('hero.png')
.resize(1200, 630, { fit: 'cover' })
.avif({ quality: 65 })
.toFile('hero.avif');
Delivery
Responsive images via srcset and sizes attributes mean the browser downloads only the resolution it needs. A 375px-wide phone shouldn't pull down a 2400px image. The <picture> element with <source> tags lets you serve AVIF to supporting browsers with WebP or JPEG fallbacks.
CDNs like Cloudflare Images, Imgix, and Vercel's built-in image optimization handle format negotiation, resizing, and caching at the edge. You upload one source file and the CDN does the rest via content negotiation with the Accept header.
When to use it
Honest answer: always. Every production site should optimize images. The specific techniques vary, though.
Go aggressive when:
- Hero images or product photos are your LCP element
- You're targeting mobile users on constrained networks
- Your page has 10+ images (galleries, e-commerce PLPs)
- Core Web Vitals scores are failing the 75th percentile threshold
Lighter-touch when:
- Images are small UI icons (consider inline SVG instead)
- You're behind a CDN that already handles format conversion
- Content is user-generated and you need to balance processing cost vs. savings
Skip manual optimization when:
- You're using Next.js
<Image>(or Astro's<Image>)—these components handle resizing, format selection, and lazy loading out of the box. We default to these on every project. Only drop to manual Sharp pipelines for edge cases like OG image generation.
Image Optimization vs alternatives
| Approach | Pros | Cons |
|---|---|---|
| Manual (Sharp, Squoosh CLI) | Full control over quality/format, no runtime cost | Requires build step, manual srcset management |
| Framework built-in (Next.js Image, Astro Image) | Zero-config, automatic format negotiation, lazy loading | Tied to framework, serverless function cost on Vercel |
| CDN-based (Cloudflare Images, Imgix) | Edge delivery, on-the-fly transforms, no build step | Monthly cost, vendor lock-in on URL structure |
| CMS plugins (WordPress Smush, ShortPixel) | Easy for non-developers | Limited format support, adds plugin weight |
Our preferred stack: Astro's <Image> component for static sites, Next.js <Image> for dynamic apps, with Cloudflare as the CDN layer. We've shipped this combo on 50+ projects and it consistently gets LCP under 2s without manual tuning.
Real-world example
On a recent e-commerce rebuild (Astro + Shopify Storefront API), the existing site served uncompressed 2400×1600 JPEG product images at ~1.8 MB each. The product listing page loaded 24 images above and below the fold—total image payload was 18+ MB.
We applied three changes: converted to AVIF with WebP fallback via Astro's <Image>, generated srcset breakpoints at 400/800/1200px widths, and added loading="lazy" to everything except the first four visible products. Result: average image size dropped to ~85 KB, total page image payload went from 18 MB to 1.2 MB, and LCP on mobile (Moto G Power on 4G, tested via WebPageTest) dropped from 5.8s to 1.4s. Lighthouse performance score jumped from 38 to 94.