Image Optimization for the Web: Formats, Compression, and Delivery
Why image optimization matters
Images account for roughly 50% of the average web page's total weight. On image-heavy pages (portfolios, e-commerce, real estate), it can be 80%+. Unoptimized images are the single most impactful performance problem on the web — and the easiest to fix.
A single uncompressed 5MB hero image takes over 10 seconds to download on a 4G connection. Multiply that across multiple images on a page and your site becomes unusable on mobile.
Image optimization isn't just about compression. It's a combination of:
- Choosing the right format for each use case
- Compressing to the smallest file size without visible quality loss
- Serving the correct dimensions for each screen size
- Lazy loading images that aren't immediately visible
- Using a CDN for fast delivery from edge locations
Choosing the right image format
Each format has specific strengths. Using the wrong one wastes bandwidth:
- AVIF — The best modern format. 50% smaller than JPEG at equivalent quality, supports transparency and HDR. Browser support is now at ~93%. Use AVIF as your primary format with fallbacks.
- WebP — 25-35% smaller than JPEG, supports transparency and animation. ~97% browser support. Your safe default when AVIF isn't available.
- JPEG — The fallback for older browsers. Good compression for photographs. No transparency support.
- PNG — Use only when you need lossless transparency (logos, icons with transparency). Much larger than WebP/AVIF for photographs.
- SVG — Vector format for icons, logos, and simple illustrations. Infinitely scalable, tiny file size, CSS-styleable. Always use SVG for icons — never rasterize them.
- GIF — Avoid for animations. Use MP4/WebM video instead (90%+ smaller file size) or animated WebP.
Serve multiple formats with the <picture> element:
<picture>
<source srcset="/hero.avif" type="image/avif">
<source srcset="/hero.webp" type="image/webp">
<img src="/hero.jpg" alt="Hero image description" width="1200" height="600">
</picture>
The browser picks the first supported format automatically.
Tip
In Next.js, the built-in <code><Image></code> component handles format negotiation automatically — it serves AVIF or WebP based on the browser's Accept header. If you're using Next.js, use it.
Compression: balancing quality and file size
Lossy compression removes data the human eye can barely detect. The key is finding the sweet spot where files are small but quality remains visually indistinguishable from the original.
Recommended quality settings:
- AVIF: quality 40-50 (looks great, dramatic size reduction)
- WebP: quality 75-85
- JPEG: quality 75-85 (below 70 artifacts become visible)
Command-line tools:
# Convert and compress with sharp (Node.js)
npx sharp-cli -i input.jpg -o output.avif --format avif --quality 45
npx sharp-cli -i input.jpg -o output.webp --format webp --quality 80
# Using cwebp (Google's WebP encoder)
cwebp -q 80 input.jpg -o output.webp
# Using avifenc
avifenc --min 20 --max 50 input.png output.avif
# Batch convert all JPEGs in a directory
for f in *.jpg; do cwebp -q 80 "$f" -o "${f%.jpg}.webp"; done
Build-time optimization: Use tools like sharp, imagemin, or squoosh-cli in your build pipeline to automatically compress images on deploy. Never rely on developers remembering to compress manually.
Responsive images: right size for every screen
Serving a 3000px-wide image to a 375px phone screen wastes ~90% of the downloaded data. Responsive images solve this by letting the browser choose the right size:
<img
srcset="
/hero-400.webp 400w,
/hero-800.webp 800w,
/hero-1200.webp 1200w,
/hero-1600.webp 1600w
"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 1200px"
src="/hero-1200.webp"
alt="Hero section"
width="1600"
height="800"
loading="lazy"
>
Key rules:
- Generate 4-6 size variants for key images (400, 800, 1200, 1600, 2000px widths)
- The
sizesattribute tells the browser how wide the image will be displayed — without this, it assumes full viewport width - Always set explicit
widthandheightattributes to prevent layout shift (CLS) - Don't upscale — never serve an image larger than the original
Tip
Image CDNs like Cloudinary, imgix, or Cloudflare Images can generate responsive variants on the fly via URL parameters. This eliminates the need to pre-generate sizes in your build.
Lazy loading: load images only when needed
Lazy loading defers loading images until they're about to scroll into view. On a page with 30 images, this might mean loading only 3-4 on initial page load — dramatically reducing Time to Interactive.
Native lazy loading (recommended):
<!-- Lazy load below-the-fold images -->
<img src="/product.webp" alt="Product photo" loading="lazy" width="600" height="400">
<!-- Do NOT lazy load above-the-fold images (hero, logo) -->
<img src="/hero.webp" alt="Hero" loading="eager" fetchpriority="high" width="1200" height="600">
Critical rules:
- Never lazy load the LCP image — your hero image or main product image should load eagerly with
fetchpriority="high". Lazy loading it will destroy your LCP score. - Always include
widthandheight(or use CSS aspect-ratio) to reserve space and prevent layout shift. - Native
loading="lazy"has ~96% browser support — no JavaScript library needed. - For iframes (YouTube embeds, maps), use
loading="lazy"as well — embedded iframes are often the heaviest resources on a page.
Image CDNs and automated optimization
An image CDN automatically optimizes, resizes, and delivers images from edge servers worldwide. This is the most efficient approach for sites with many images:
- Cloudflare Images / Polish — Automatic WebP/AVIF conversion, resizing via URL params. Included with Cloudflare Pro ($20/mo) or Images ($5/mo + usage).
- Cloudinary — Powerful transformation API. Free tier: 25K transformations/mo. URL-based:
https://res.cloudinary.com/demo/image/upload/w_800,q_auto,f_auto/sample.jpg - imgix — High-performance image CDN with real-time processing. Popular with media-heavy sites.
- Vercel Image Optimization — Built into Next.js deployments on Vercel. Automatic format selection and resizing.
The key feature to look for is automatic format negotiation — the CDN detects the browser's supported formats via the Accept header and serves the optimal format (AVIF → WebP → JPEG) without any changes to your HTML.
Frequently Asked Questions
Related Articles
Check how your website performs in this area
Get Your Growth Score