Guide

How to Optimize Images for Web: The Complete Guide

A seven-step process for reducing image file sizes without visible quality loss — covering format choice, resizing, compression, metadata, and delivery techniques that improve Core Web Vitals.

Why image optimization matters

Images are typically the largest assets on any web page, often accounting for 50–80% of total page weight. Unoptimized images cause slow page loads, hurt Core Web Vitals scores, and waste bandwidth — especially for mobile users on limited data plans.

Google's Core Web Vitals directly measure image performance:

  • Largest Contentful Paint (LCP): Measures how quickly the largest visible element (usually a hero image) loads. Google considers LCP under 2.5 seconds "good" — slow images are the primary cause of poor LCP scores.
  • Cumulative Layout Shift (CLS): Images without explicit width/height attributes cause layout shifts as they load, contributing to CLS. Always specify dimensions.
  • Interaction to Next Paint (INP): Heavy image processing in the browser can block the main thread and degrade responsiveness.

Beyond performance metrics, optimized images reduce hosting bandwidth costs and improve user experience on slow connections.

Step 1: Choose the right format

The choice of image format determines the ceiling for how small the file can get. The right format depends on the image type:

  • Photographs: WebP (lossy) as primary, JPEG as fallback. WebP produces 25–35% smaller files than JPEG at equivalent visual quality. For cutting-edge compression: AVIF saves an additional 20–30% over WebP but requires a <picture> element with fallback.
  • Logos, icons, flat graphics: SVG if the source is vector. WebP lossless if rasterized. PNG-8 for legacy support contexts. Never JPEG for graphics — DCT compression creates visible artifacts on sharp edges.
  • Images with transparency: WebP (supports alpha in both lossy and lossless modes), PNG as fallback. Never JPEG — it does not support transparency.
  • Animations: MP4 (H.264 or H.265) instead of GIF. An animated GIF that is 10 MB typically converts to under 500 KB as MP4 with better quality and smoother playback. Use <video autoplay loop muted playsinline> instead of <img>.
  • UI screenshots and diagrams: WebP lossless or PNG. These contain text and sharp edges that JPEG compresses poorly.

Step 2: Resize to the display dimensions

Serving an image larger than its display size is the single most common and wasteful optimization mistake. A photo that displays at 800px wide on a desktop layout should be served at 800px wide (or 1600px for 2× retina), not at its original 4000px camera resolution.

How to calculate the right size:

  • Determine the maximum CSS display size for the image across all breakpoints.
  • Multiply by 2 for retina/2× display support (1600px for an 800px CSS width).
  • For images that span the full viewport width, use the viewport width at your widest breakpoint.

Savings from resizing: Quadratic. Halving the pixel dimensions reduces file size by approximately 75%. A 4000px image at 400 KB resized to 1600px is approximately 65 KB — a 84% reduction before any compression changes.

For responsive images that need to serve different sizes to different viewports, use the srcset attribute to provide multiple resolutions rather than serving the largest size to everyone.

Step 3: Compress to the right quality level

After resizing, apply lossy compression to reduce file size further. The quality setting controls the tradeoff between file size and visual fidelity. Quality above 85 (for JPEG/WebP) adds minimal visual benefit while increasing file size substantially.

Image typeJPEG qualityWebP qualityAVIF quality
Hero / product images85–9080–8570–80
Standard content images80–8575–8262–72
Thumbnails70–7565–7255–65
Background / decorative60–7055–6545–58
Archival / print delivery90–9590–9582–90

Test your output visually at actual display size before deploying. Zooming in 400% on a thumbnail shows artifacts that are invisible at normal size — optimize for how the image will actually be viewed.

Step 4: Strip metadata

Image files accumulate metadata: EXIF camera data, GPS coordinates, color profiles, thumbnails, XMP editing history, and copyright information. This metadata adds 5–30 KB per image without affecting the visible image.

What to strip: EXIF, IPTC, XMP, and embedded thumbnails. Stripping these is always safe for web delivery and removes any privacy-sensitive GPS data.

What to be careful with: ICC color profiles. For sRGB images, stripping the profile is safe — browsers assume sRGB by default. For images in Adobe RGB or Display P3, strip the profile only after converting the image to sRGB first. Stripping a non-sRGB profile without converting causes colors to render incorrectly.

Step 5: Use lazy loading

Lazy loading defers the download of off-screen images until the user scrolls near them, reducing the amount of data downloaded on initial page load. The browser handles this natively with the loading attribute:

<img src="photo.webp" alt="Description" width="800" height="600" loading="lazy">

Critical rule: Never lazy-load above-the-fold images — the hero image, logo, or any image visible when the page first renders. Lazy loading these delays their fetch and directly worsens Largest Contentful Paint scores. Only apply loading="lazy" to images below the fold.

Always include width and height attributes on every image. This lets the browser reserve the correct space before the image loads, preventing layout shifts (which contribute to Cumulative Layout Shift scores).

Step 6: Serve responsive images

Instead of serving one image size to all viewports, use srcset to provide multiple versions and let the browser choose the right one based on the viewport and device pixel ratio:

<img
  src="photo-800.webp"
  srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1600.webp 1600w"
  sizes="(max-width: 600px) 100vw, 800px"
  alt="Description"
  width="800" height="600"
>

For format fallbacks (AVIF → WebP → JPEG), use the <picture> element:

<picture>
  <source srcset="photo.avif" type="image/avif">
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" alt="Description" width="800" height="600">
</picture>

The browser downloads only the first format it supports — older browsers fall through to the <img> JPEG fallback.

Step 7: Set cache headers

Images rarely change. Set long cache durations so that returning visitors and CDN nodes serve images from cache rather than re-downloading them:

Cache-Control: public, max-age=31536000, immutable

The immutable directive tells browsers the resource will never change, so they skip revalidation requests. Use content-hashed filenames (e.g., hero-a3f9b2c1.webp) so that when an image does change, the new filename forces a fresh download rather than serving a stale cached version.

For image CDNs (Cloudflare Images, Imgix, Cloudinary), caching is typically handled automatically. Ensure your origin images are also cached so the CDN can serve from edge nodes rather than fetching from origin on every request.

Optimization checklist

  • Format: photographs in WebP, graphics in SVG or WebP lossless, animations in MP4
  • Dimensions: sized to the maximum display size × device pixel ratio (no larger)
  • Compression: quality 80–85 for WebP photographs, 75–82 for thumbnails
  • Metadata: stripped (EXIF, IPTC, XMP, thumbnails)
  • Lazy loading: loading="lazy" on all below-fold images
  • No lazy loading on above-fold / hero images
  • Width and height attributes on every <img> element
  • Responsive sizes via srcset for images with varying display widths
  • Cache headers: max-age=31536000, immutable with content-hashed filenames
  • AVIF format (with WebP fallback) for maximum compression on modern browsers

Frequently asked questions

What is the most important image optimization step?

Resizing to the correct display dimensions. A photo exported at 4000px wide but displayed at 800px transfers five times more data than needed. Resizing to the actual display size (multiplied by device pixel ratio for retina support) produces the biggest file size reduction of any single optimization step.

Does image optimization affect SEO?

Yes, significantly. Google's Core Web Vitals include Largest Contentful Paint (LCP), which measures how quickly the largest visible element (usually a hero image) loads. Slow LCP scores are associated with lower search rankings. Optimizing images — especially above-the-fold ones — directly improves LCP and therefore SEO.

What compression quality should I use for web images?

For JPEG: 80–85 for standard images, 85–90 for hero and product images. For WebP: 75–85 for standard images. For AVIF: 60–70 for standard images. These settings produce images that look identical to the original at normal viewing sizes while reducing file size by 30–60% compared to higher quality settings.

Should I use lazy loading for all images?

Use lazy loading for images below the fold — those not visible when the page first loads. Do not use lazy loading for above-the-fold images (your hero image, logo, or any image visible on first paint). Lazy loading above-the-fold images delays their load and worsens LCP scores. The HTML attribute is loading="lazy" on the <img> element.

Web optimization tools