Skip to main content
Beta: Front-End Checklist is currently in beta. Some issues are still being fixed. Thanks for your patience.

Optimize all images for web

Images are optimized with appropriate formats, compression, and modern techniques.

Utilities
Quick take
Typical fix time 20 min
  • Use modern formats: AVIF > WebP > JPEG/PNG
  • Compress images to 80% quality for photos
  • Always provide responsive srcset for different screen sizes
  • Use `<picture>` element for format fallbacks
Why it matters: Images typically account for 50%+ of page weight. Unoptimized images cause slow load times, wasted bandwidth, poor Core Web Vitals scores, and frustrated users—especially on mobile networks.

Rule Details

Image optimization is crucial for web performance. Properly optimized images can reduce page weight by 50-80% without visible quality loss, directly improving Largest Contentful Paint (LCP) (opens in new tab) and user experience.

Good to Know

Use the <picture> element with multiple sources to serve modern formats (AVIF, WebP) to supported browsers while providing JPEG/PNG fallbacks for older browsers.

Code Example

Choose the right format based on image content and browser support.

<!-- Modern format with fallbacks -->
<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="Description" loading="lazy">
</picture>

Format Comparison

FormatBest ForCompressionBrowser Support
AVIFAll images~50% smaller than JPEGModern browsers
WebPAll images~30% smaller than JPEG95%+ browsers
JPEGPhotosGoodUniversal
PNGTransparency, logosLarger filesUniversal
SVGIcons, illustrationsScalableUniversal
Format Support

Always provide fallbacks when using AVIF or WebP. Safari only added AVIF support in version 16.4 (2023), and some enterprise browsers may lack WebP support.

Why It Matters

Images typically account for 50%+ of page weight. Unoptimized images cause slow load times, wasted bandwidth, poor Core Web Vitals scores, and frustrated users—especially on mobile networks.

Responsive Images

Serve appropriately sized images for different screen sizes to avoid downloading unnecessarily large files.

<!-- ✅ Good: Responsive with srcset -->
<img
  src="image-800w.jpg"
  srcset="
    image-400w.jpg 400w,
    image-800w.jpg 800w,
    image-1200w.jpg 1200w,
    image-1600w.jpg 1600w
  "
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
  alt="Responsive image"
  loading="lazy"
>
 
<!-- ❌ Bad: Single large image for all screens -->
<img src="image-1600w.jpg" alt="Large image">

Art Direction

Use <picture> for different crops or aspect ratios at different breakpoints.

<picture>
  <!-- Mobile: Square crop -->
  <source media="(max-width: 600px)" srcset="hero-square.webp">
  <!-- Tablet: 4:3 aspect -->
  <source media="(max-width: 1024px)" srcset="hero-4x3.webp">
  <!-- Desktop: Wide banner -->
  <img src="hero-wide.jpg" alt="Hero image">
</picture>

Framework Examples

function OptimizedImage({ src, alt, sizes = "100vw" }) {
  // Generate srcset for multiple sizes
  const widths = [400, 800, 1200, 1600]
  const srcset = widths
    .map(w => `${src}?w=${w} ${w}w`)
    .join(', ')
 
  return (
    <picture>
      {/* Modern formats */}
      <source
        type="image/avif"
        srcSet={srcset.replace(/\?w=/g, '?format=avif&w=')}
        sizes={sizes}
      />
      <source
        type="image/webp"
        srcSet={srcset.replace(/\?w=/g, '?format=webp&w=')}
        sizes={sizes}
      />
      {/* Fallback */}
      <img
        src={`${src}?w=800`}
        srcSet={srcset}
        sizes={sizes}
        alt={alt}
        loading="lazy"
        decoding="async"
        className="w-full h-auto"
      />
    </picture>
  )
}
 
// Progressive loading with blur-up
function ProgressiveImage({ src, placeholder, alt }) {
  const [loaded, setLoaded] = useState(false)
  const [currentSrc, setCurrentSrc] = useState(placeholder)
 
  useEffect(() => {
    const img = new Image()
    img.onload = () => {
      setCurrentSrc(src)
      setLoaded(true)
    }
    img.src = src
  }, [src])
 
  return (
    <img
      src={currentSrc}
      alt={alt}
      className={`transition-all duration-300 ${
        loaded ? 'blur-0' : 'blur-sm'
      }`}
    />
  )
}

Build Tool Integration

Vite with Sharp

// vite.config.js
import { defineConfig } from 'vite'
import { viteImageOptimizer } from 'vite-plugin-image-optimizer'
 
export default defineConfig({
  plugins: [
    viteImageOptimizer({
      jpg: { quality: 80, progressive: true },
      png: { quality: 80 },
      webp: { quality: 80, effort: 6 },
      avif: { quality: 60, effort: 6 }
    })
  ]
})

Sharp Script for Batch Processing

// scripts/optimize-images.js
const sharp = require('sharp')
const fs = require('fs').promises
const path = require('path')
 
const SIZES = [400, 800, 1200, 1600]
const FORMATS = ['webp', 'avif', 'jpeg']
 
async function optimizeImage(inputPath, outputDir) {
  const { name } = path.parse(inputPath)
 
  for (const width of SIZES) {
    for (const format of FORMATS) {
      const outputPath = path.join(outputDir, `${name}-${width}w.${format}`)
 
      await sharp(inputPath)
        .resize(width, null, { withoutEnlargement: true })
        .toFormat(format, {
          quality: format === 'avif' ? 60 : 80,
          effort: 6
        })
        .toFile(outputPath)
    }
  }
 
  console.log(`✅ Optimized: ${name}`)
}
Quick Win

Use a CDN with automatic image optimization like Cloudflare Images, Imgix, or Cloudinary. They handle format negotiation, resizing, and compression automatically based on the visitor's browser and device.

Common Mistakes

Mistakes to Avoid
  • Serving desktop images to mobile — Use srcset and sizes for responsive images
  • Missing width/height attributes — Causes layout shift (CLS issues)
  • Over-compressing — Quality below 60% causes visible artifacts
  • Ignoring format fallbacks — Not all browsers support AVIF/WebP
  • No lazy loading — Loads all images immediately, blocking page render
  • Huge hero images — Prioritize and optimize above-the-fold images
<!-- ❌ Bad: Common mistakes -->
<img src="photo.png" alt="Photo"><!-- PNG for photos -->
<img src="hero-4000px.jpg"><!-- No responsive sizing -->
<img src="icon.jpg" width="20"><!-- JPEG for small icon -->
 
<!-- ✅ Good: Optimized versions -->
<picture>
  <source srcset="photo.avif" type="image/avif">
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" alt="Photo" loading="lazy">
</picture>
 
<img
  srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
  sizes="100vw"
  src="hero-800.jpg"
  alt="Hero"
  width="1200"
  height="600"
>
 
<img src="icon.svg" alt="Icon" width="20" height="20"><!-- SVG for icons -->
When to Break This Rule
  • SVG images don't need format conversion—they're already optimized for web
  • Animated GIFs may be better served as videos (MP4/WebM) for large animations
  • Tiny images (< 1KB) can be inlined as base64 data URIs to avoid HTTP requests
  • User-uploaded content may need server-side optimization pipelines rather than build-time processing

Support Notes

  • Image format and delivery behavior can vary by browser, CDN, and device characteristics, so verify the final bytes and rendered output on the supported browser matrix.
  • Add a fallback note when a modern format or loading behavior is not available for every required target browser.

Verification

Automated Checks

  • Test on slow connections — Use Chrome DevTools Network throttling (Slow 3G)
  • Measure LCP — Use Lighthouse or Web Vitals extension to ensure LCP < 2.5s

Manual Checks

  • Check file sizes — Images should generally be under 200KB for photos, under 50KB for icons
  • Verify format negotiation — Check Network tab to confirm WebP/AVIF is served

Use with AI

Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.

Check

Verify implementation

Scan this codebase for all image assets and <img> elements. For each image, verify: 1) Format is appropriate (WebP/AVIF for photos, SVG for icons, PNG only for transparency). 2) Responsive srcset and sizes attributes exist for images > 100px wide. 3) width/height attributes are present to prevent layout shift. 4) loading='lazy' is set for below-fold images. 5) File sizes are reasonable (< 200KB for photos, < 50KB for graphics). Report issues grouped by severity with file paths.

Fix

Auto-fix issues

For each image optimization issue found: 1) Convert JPEG/PNG photos to WebP with AVIF fallback using <picture> element. 2) Add srcset with 400w, 800w, 1200w, 1600w variants and appropriate sizes attribute. 3) Add explicit width/height attributes matching aspect ratio. 4) Add loading='lazy' to images below the fold, keep priority images without lazy loading. 5) Compress images to 80% quality for photos, 60% for AVIF. 6) Use SVG for icons and logos. Show the corrected HTML with optimized image markup.

Explain

Learn more

Explain the impact of image optimization on Core Web Vitals, specifically how unoptimized images affect Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS). Cover the compression differences between AVIF, WebP, and JPEG formats, when to use each, and browser support considerations. Describe how srcset and sizes work together to serve appropriately-sized images, and why width/height attributes prevent layout shift. Include bandwidth savings calculations and loading performance improvements.

Review

Code review

Review image assets, markup, and delivery configuration related to Optimize all images for web. Flag exact files or components where format choice, sizing, or loading behavior violates the rule, and describe how to confirm the fix in DevTools.

Sources

References used to support the guidance in this rule.

Further Reading

Tools and supplementary material for exploring the topic in more depth.

Optimize images

by web.dev

web.devArticle
Modern Image Formats

by web.dev

web.devDocs
Image Optimization in Next.js

by Vercel

nextjs.orgDocs
Image Performance

by Google Chrome Developers

youtube.comVideo
Squooshsquoosh.appTool
Sharpsharp.pixelplumbing.comTool
ImageOptimimageoptim.comTool
Lighthousedeveloper.chrome.comTool

Rules that often go hand-in-hand with this one.

Implement lazy loading for offscreen content

Images and heavy resources below the fold are lazy loaded to improve initial performance.

Performance
Implement responsive images with srcset

Images use srcset and sizes attributes for responsive delivery across devices.

Images
Use WebP format with fallbacks

Images are served in WebP format with fallbacks for older browsers.

Images
Use AVIF format for modern browsers

Images support AVIF format for superior compression with proper browser fallbacks.

Images

Was this rule helpful?

Your feedback helps improve rule quality. This stays internal for now.

Loading feedback...
0 / 385