Detailed guide

Image Optimization Guide

View contents

Complete Guide to Image Optimization for Web Performance

Introduction

Images typically account for the largest portion of bytes downloaded on a webpage. Optimizing images can significantly improve both performance metrics and user experience. This guide provides comprehensive strategies for implementing image optimization at every level.

New to image optimization? Start with our beginner-friendly guide: 📖 Read: Image Optimization Explained

Strategy 1: Choose the Right Image Format

Modern Formats Comparison

Format Selection Decision Tree:
┌─────────────────────────────────────────────────────────────┐
│ Is it a photograph or complex image?                        │
│ ├── YES                                                     │
│ │   └── Use AVIF (primary) → WebP (fallback) → JPEG        │
│ │                                                           │
│ └── NO (icon, logo, illustration)                          │
│     ├── Does it need animation?                            │
│     │   ├── YES → Use animated WebP or video               │
│     │   └── NO                                             │
│     │       ├── Is it scalable vector art?                 │
│     │       │   ├── YES → Use SVG                          │
│     │       │   └── NO → Use PNG or WebP                   │
│     └── Does it need transparency?                         │
│         ├── YES → Use WebP or PNG                          │
│         └── NO → Use WebP or JPEG                          │
└─────────────────────────────────────────────────────────────┘

Implementing Progressive Enhancement with Picture

<picture>
  <!-- AVIF: Best compression, growing support -->
  <source
    srcset="image.avif"
    type="image/avif"
  >
  <!-- WebP: Good compression, excellent support -->
  <source
    srcset="image.webp"
    type="image/webp"
  >
  <!-- JPEG: Universal fallback -->
  <img
    src="image.jpg"
    alt="Descriptive alt text"
    width="800"
    height="600"
    loading="lazy"
  >
</picture>

Format Compression Comparison

Format Photo (1000x800) Compression Quality
Original JPEG 450 KB - 100%
Optimized JPEG (q85) 180 KB 60% smaller 95%
WebP (q85) 120 KB 73% smaller 95%
AVIF (q80) 75 KB 83% smaller 95%

Strategy 2: Implement Responsive Images

Using srcset and sizes

<img
  src="hero-800.jpg"
  srcset="
    hero-400.jpg 400w,
    hero-600.jpg 600w,
    hero-800.jpg 800w,
    hero-1200.jpg 1200w,
    hero-1600.jpg 1600w
  "
  sizes="
    (max-width: 400px) 100vw,
    (max-width: 800px) 100vw,
    (max-width: 1200px) 80vw,
    1200px
  "
  alt="Hero image description"
  width="1600"
  height="900"
>

Understanding sizes Attribute

sizes Calculation Examples:
┌─────────────────────────────────────────────────────────────┐
│ sizes="(max-width: 600px) 100vw, 50vw"                      │
│                                                             │
│ On 400px viewport:                                          │
│ → Image width = 100vw = 400px                               │
│ → Browser selects 400w image                                │
│                                                             │
│ On 1200px viewport:                                         │
│ → Image width = 50vw = 600px                                │
│ → Browser selects 600w or 800w image (depends on DPR)       │
│                                                             │
│ On 1200px viewport with 2x DPR (Retina):                    │
│ → Image width = 50vw = 600px × 2 = 1200px effective         │
│ → Browser selects 1200w image                               │
└─────────────────────────────────────────────────────────────┘

Art Direction with Picture Element

Use <picture> when you need different crops for different screen sizes:

<picture>
  <!-- Mobile: Square crop, centered on subject -->
  <source
    media="(max-width: 600px)"
    srcset="product-mobile.webp"
    type="image/webp"
  >
  <source
    media="(max-width: 600px)"
    srcset="product-mobile.jpg"
  >

  <!-- Desktop: Wide landscape crop -->
  <source
    srcset="product-desktop.webp"
    type="image/webp"
  >
  <img
    src="product-desktop.jpg"
    alt="Product name - detailed view"
    width="1200"
    height="600"
  >
</picture>

Strategy 3: Optimize Loading Priority

Fetchpriority for Critical Images

<!-- LCP image: Load with highest priority -->
<img
  src="hero.webp"
  alt="Hero image"
  fetchpriority="high"
  decoding="async"
  width="1200"
  height="600"
>

<!-- Below-fold images: Lower priority, lazy load -->
<img
  src="gallery-1.webp"
  alt="Gallery image 1"
  loading="lazy"
  decoding="async"
  width="400"
  height="300"
>

Preloading Critical Images

<head>
  <!-- Preload LCP image with format hints -->
  <link
    rel="preload"
    as="image"
    href="hero.webp"
    type="image/webp"
    fetchpriority="high"
  >

  <!-- Preload responsive image -->
  <link
    rel="preload"
    as="image"
    href="hero-1200.webp"
    imagesrcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
    imagesizes="(max-width: 600px) 100vw, 1200px"
  >
</head>

Lazy Loading Best Practices

<!-- ❌ Wrong: Lazy loading LCP/above-fold images -->
<img src="hero.jpg" loading="lazy" alt="Hero">

<!-- ✅ Correct: Only lazy load below-fold images -->
<img src="hero.jpg" fetchpriority="high" alt="Hero">

<section class="below-fold">
  <img src="product-1.jpg" loading="lazy" alt="Product 1">
  <img src="product-2.jpg" loading="lazy" alt="Product 2">
</section>

Strategy 4: Compression and Quality

Compression Tool Comparison

Tool Type Best For Quality Control
Squoosh Web app Manual optimization, testing Visual comparison
Sharp Node.js Build pipelines, automation Numeric quality
ImageOptim Desktop (Mac) Batch optimization Automatic
svgo CLI SVG optimization Size reduction

Build Pipeline Integration

// Sharp example for Node.js build
const sharp = require('sharp');

async function optimizeImage(inputPath, outputPath) {
  await sharp(inputPath)
    // Resize to max dimensions
    .resize(1600, 900, {
      fit: 'inside',
      withoutEnlargement: true
    })
    // Output as WebP
    .webp({
      quality: 85,
      effort: 6
    })
    .toFile(outputPath.replace(/\.\w+$/, '.webp'));

  // Also create AVIF version
  await sharp(inputPath)
    .resize(1600, 900, {
      fit: 'inside',
      withoutEnlargement: true
    })
    .avif({
      quality: 80,
      effort: 6
    })
    .toFile(outputPath.replace(/\.\w+$/, '.avif'));
}

Quality Guidelines

Quality Settings by Use Case:
┌─────────────────────────────────────────────────────────────┐
│ Use Case              │ JPEG/WebP │ AVIF  │ Notes           │
│───────────────────────│───────────│───────│─────────────────│
│ Hero images           │ 85-90     │ 80-85 │ High quality    │
│ Product photos        │ 85        │ 80    │ Detail matters  │
│ Blog thumbnails       │ 75-80     │ 70-75 │ Can be lower    │
│ Background patterns   │ 60-70     │ 55-65 │ Lower priority  │
│ Icons/logos (WebP)    │ 90-100    │ -     │ Keep crisp      │
└─────────────────────────────────────────────────────────────┘

Strategy 5: Prevent Layout Shift

Always Include Dimensions

<!-- ✅ Correct: Explicit dimensions -->
<img
  src="product.jpg"
  width="400"
  height="300"
  alt="Product"
>

<!-- ✅ Also correct: CSS aspect-ratio -->
<style>
  .product-image {
    aspect-ratio: 4/3;
    width: 100%;
    height: auto;
  }
</style>
<img src="product.jpg" class="product-image" alt="Product">

Container-Based Sizing

<div class="image-container">
  <img
    src="image.jpg"
    alt="Description"
    loading="lazy"
  >
</div>

<style>
.image-container {
  position: relative;
  padding-bottom: 56.25%; /* 16:9 aspect ratio */
  height: 0;
  overflow: hidden;
}

.image-container img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
</style>

Strategy 6: Image CDN and Optimization Services

Benefits of Image CDNs

  1. Automatic format conversion - Serve WebP/AVIF based on browser support
  2. On-the-fly resizing - Generate responsive sizes dynamically
  3. Global edge caching - Faster delivery worldwide
  4. URL-based transformations - No build step required

Example: Cloudinary URL Transformations

<!-- Original -->
<img src="https://res.cloudinary.com/demo/image/upload/sample.jpg">

<!-- Optimized: Auto format, quality, and size -->
<img src="https://res.cloudinary.com/demo/image/upload/
  f_auto,
  q_auto,
  w_800,
  c_limit
  /sample.jpg">

<!-- Responsive with srcset -->
<img
  src="https://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_800/sample.jpg"
  srcset="
    https://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_400/sample.jpg 400w,
    https://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_800/sample.jpg 800w,
    https://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_1200/sample.jpg 1200w
  "
  sizes="(max-width: 600px) 100vw, 800px"
  alt="Sample image"
>

Strategy 7: SVG Optimization

SVGO Configuration

// svgo.config.js
module.exports = {
  plugins: [
    'removeDoctype',
    'removeXMLProcInst',
    'removeComments',
    'removeMetadata',
    'removeEditorsNSData',
    'cleanupAttrs',
    'mergeStyles',
    'inlineStyles',
    'minifyStyles',
    'cleanupIds',
    'removeUselessDefs',
    'removeUselessStrokeAndFill',
    'removeHiddenElems',
    'removeEmptyText',
    'removeEmptyAttrs',
    'removeEmptyContainers',
    'convertPathData',
    'mergePaths',
    {
      name: 'removeViewBox',
      active: false  // Keep viewBox for responsive scaling
    }
  ]
};

Inline SVG Best Practices

<!-- For icons used multiple times: use sprite -->
<svg style="display: none;">
  <symbol id="icon-search" viewBox="0 0 24 24">
    <path d="..."/>
  </symbol>
  <symbol id="icon-menu" viewBox="0 0 24 24">
    <path d="..."/>
  </symbol>
</svg>

<!-- Usage -->
<svg aria-label="Search"><use href="#icon-search"/></svg>
<svg aria-label="Menu"><use href="#icon-menu"/></svg>

Measuring Improvements

Before/After Comparison

BEFORE Optimization:
├── Total image weight: 2.8 MB
├── LCP: 4.2s
├── Number of images: 15
├── Lighthouse Image Score: 45
└── CLS (image-related): 0.15

AFTER Optimization:
├── Total image weight: 450 KB (↓84%)
├── LCP: 1.8s (↓57%)
├── Number of images: 15 (same)
├── Lighthouse Image Score: 100
└── CLS (image-related): 0 (↓100%)

Lighthouse Audits to Check

  • “Properly size images” - Serving correct dimensions
  • “Serve images in next-gen formats” - WebP/AVIF usage
  • “Efficiently encode images” - Compression applied
  • “Defer offscreen images” - Lazy loading implemented
  • “Image elements have explicit width and height” - CLS prevention

Optimization Checklist

Before deploying, verify:

  • [ ] Hero/LCP images use fetchpriority="high"
  • [ ] Below-fold images use loading="lazy"
  • [ ] All images have width and height attributes
  • [ ] WebP (or AVIF) versions available with fallbacks
  • [ ] srcset implemented for responsive images
  • [ ] sizes attribute accurately reflects layout
  • [ ] Images compressed to appropriate quality
  • [ ] SVGs optimized with SVGO
  • [ ] Alt text is descriptive and unique
  • [ ] File names are descriptive and SEO-friendly

Continue optimizing your site’s visual performance:

📚 Back to Performance SEO Hub - Explore all performance topics


References

  1. MDN Web Docs - Responsive Images
  2. web.dev - Optimize Images
  3. Chrome Developers - Efficiently Encode Images
  4. Ahrefs - Image SEO

Try It Yourself

Ready to optimize your images?

🔧 Download UXR SEO Analyzer (Free, 100% local analysis)


Disclaimer: The analyzers in this extension are reference guides based on official documentation from MDN, web.dev, and Chrome Developers. They do not represent absolute truths about how search engines evaluate your content—only search engines know their internal algorithms. Use these recommendations as a starting point to improve your site.

Last updated: December 14, 2025

Related articles

Related version

Detailed guide

Image Optimization Explained

Images are often the largest resources on a webpage, accounting for 40-60% of total page weight on most websites

Category hub

Hub

Performance Seo Hub

Performance is a critical ranking factor and directly impacts user experience

In the same category

Detailed guide

Lcp Optimization Guide

Largest Contentful Paint (LCP) measures when the largest content element becomes visible to users

Detailed guide

Cls Optimization Guide

Cumulative Layout Shift (CLS) measures the visual stability of your page

Detailed guide

Render Blocking Resources Optimization Guide

Render-blocking resources are one of the most impactful performance issues you can fix