· Performance

Responsive Images: Best Practices for 2024

Optimize images for all devices and screen sizes.

Images make up the majority of bytes downloaded on most web pages. Serving the right image at the right size to the right device is critical for performance, user experience, and bandwidth costs. In this guide, you’ll learn modern techniques for responsive images including srcset, sizes, the picture element, and optimization strategies that work in 2024.

Responsive images aren’t just about scaling—they’re about delivering the perfect image for each user’s device, screen size, and network speed.

Why Responsive Images Matter

The Problem

A single 2MB image works fine on desktop with fast WiFi, but on mobile with slow 4G:

  • Takes 10+ seconds to load
  • Costs users money (limited data plans)
  • Wastes bandwidth (mobile screens don’t need 4K images)
  • Hurts performance metrics
  • Frustrates users

The Solution

Serve appropriately sized images:

  • Mobile: 400px wide image (50KB)
  • Tablet: 800px wide image (150KB)
  • Desktop: 1200px wide image (300KB)
  • Retina displays: 2x versions when needed

The srcset Attribute

The simplest responsive image technique:

<img 
  src="image-small.jpg" 
  srcset="
    image-small.jpg 400w,
    image-medium.jpg 800w,
    image-large.jpg 1200w,
    image-xlarge.jpg 1600w"
  sizes="100vw"
  alt="Responsive image">

How it works:

  • Browser picks the best image based on screen width
  • 400w means “this image is 400 pixels wide”
  • sizes tells browser how much space image will take
  • Browser considers device pixel ratio automatically

The sizes Attribute

Tell the browser how wide the image will be displayed:

<img 
  src="image.jpg"
  srcset="
    image-400.jpg 400w,
    image-800.jpg 800w,
    image-1200.jpg 1200w"
  sizes="
    (max-width: 600px) 100vw,
    (max-width: 1200px) 50vw,
    33vw"
  alt="Image">

Sizes explained:

  • Mobile (≤600px): Image takes full width (100vw)
  • Tablet (≤1200px): Image takes half width (50vw)
  • Desktop: Image takes one-third width (33vw)

The Picture Element

Use <picture> for art direction—when you need different crops or formats:

<picture>
  <!-- Modern format for supporting browsers -->
  <source 
    type="image/webp"
    srcset="
      image-400.webp 400w,
      image-800.webp 800w,
      image-1200.webp 1200w"
    sizes="100vw">
  
  <!-- AVIF (even better compression) -->
  <source 
    type="image/avif"
    srcset="
      image-400.avif 400w,
      image-800.avif 800w,
      image-1200.avif 1200w"
    sizes="100vw">
  
  <!-- Fallback to JPEG -->
  <img 
    src="image-800.jpg"
    srcset="
      image-400.jpg 400w,
      image-800.jpg 800w,
      image-1200.jpg 1200w"
    sizes="100vw"
    alt="Responsive image with modern formats">
</picture>

Art Direction

Show different images for different screen sizes:

<picture>
  <!-- Mobile: Square crop focusing on subject -->
  <source 
    media="(max-width: 600px)"
    srcset="portrait-crop.jpg">
  
  <!-- Tablet: Landscape crop -->
  <source 
    media="(max-width: 1200px)"
    srcset="landscape-crop.jpg">
  
  <!-- Desktop: Full wide image -->
  <img 
    src="full-width.jpg"
    alt="Product photo">
</picture>

Use art direction when:

  • Mobile needs a cropped/zoomed version
  • Orientation matters (portrait vs landscape)
  • Image content should change with screen size

Image Formats in 2024

Format Comparison

AVIF (Best compression, newest)

  • 50% smaller than JPEG
  • Supported: Chrome, Firefox, Safari 16+
  • Use with fallbacks

WebP (Great compression, widely supported)

  • 30% smaller than JPEG
  • Supported: All modern browsers
  • Safe to use with JPEG fallback

JPEG (Universal compatibility)

  • Supported everywhere
  • Good for photos
  • Always provide as fallback

PNG (Lossless, transparency)

  • Larger file sizes
  • Use for logos, graphics with transparency
  • Consider WebP/AVIF versions

Using Modern Formats

<picture>
  <!-- Best: AVIF -->
  <source type="image/avif" srcset="image.avif">
  
  <!-- Good: WebP -->
  <source type="image/webp" srcset="image.webp">
  
  <!-- Fallback: JPEG -->
  <img src="image.jpg" alt="Image description">
</picture>

Lazy Loading

Load images only when needed:

<!-- Native lazy loading -->
<img 
  src="image.jpg" 
  loading="lazy" 
  alt="Description">

<!-- Eager loading (default) -->
<img 
  src="hero.jpg" 
  loading="eager" 
  alt="Hero image">

Best practices:

  • Use loading="lazy" for below-the-fold images
  • Use loading="eager" for above-the-fold images
  • Don’t lazy-load hero images or critical content

Aspect Ratio Boxes

Prevent layout shift while images load:

<!-- Modern CSS aspect-ratio -->
<img 
  src="image.jpg" 
  alt="Description"
  style="aspect-ratio: 16/9; width: 100%; object-fit: cover;">

<!-- Width and height attributes -->
<img 
  src="image.jpg"
  width="1600"
  height="900"
  alt="Description"
  style="width: 100%; height: auto;">

Density Descriptors for Retina

Handle high-DPI displays:

<!-- Using pixel density descriptors -->
<img 
  src="image.jpg"
  srcset="
    image.jpg 1x,
    image-2x.jpg 2x,
    image-3x.jpg 3x"
  alt="Logo">

When to use:

  • Fixed-size images (logos, icons)
  • When width doesn’t change
  • Simpler than width descriptors

Complete Responsive Image Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Responsive Images Demo</title>
  <style>
    img {
      max-width: 100%;
      height: auto;
      display: block;
    }
    
    .hero-image {
      width: 100%;
      aspect-ratio: 16 / 9;
      object-fit: cover;
    }
    
    .grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
      gap: 1rem;
      padding: 1rem;
    }
  </style>
</head>
<body>
  <!-- Hero image with multiple formats -->
  <picture>
    <source 
      type="image/avif"
      srcset="
        hero-400.avif 400w,
        hero-800.avif 800w,
        hero-1200.avif 1200w,
        hero-1600.avif 1600w"
      sizes="100vw">
    
    <source 
      type="image/webp"
      srcset="
        hero-400.webp 400w,
        hero-800.webp 800w,
        hero-1200.webp 1200w,
        hero-1600.webp 1600w"
      sizes="100vw">
    
    <img 
      class="hero-image"
      src="hero-800.jpg"
      srcset="
        hero-400.jpg 400w,
        hero-800.jpg 800w,
        hero-1200.jpg 1200w,
        hero-1600.jpg 1600w"
      sizes="100vw"
      alt="Hero image"
      loading="eager"
      width="1600"
      height="900">
  </picture>
  
  <!-- Grid of lazy-loaded images -->
  <div class="grid">
    <img 
      src="product-1-400.jpg"
      srcset="
        product-1-400.jpg 400w,
        product-1-800.jpg 800w"
      sizes="
        (max-width: 600px) 100vw,
        (max-width: 1200px) 50vw,
        33vw"
      alt="Product 1"
      loading="lazy"
      width="800"
      height="600">
    
    <img 
      src="product-2-400.jpg"
      srcset="
        product-2-400.jpg 400w,
        product-2-800.jpg 800w"
      sizes="
        (max-width: 600px) 100vw,
        (max-width: 1200px) 50vw,
        33vw"
      alt="Product 2"
      loading="lazy"
      width="800"
      height="600">
  </div>
</body>
</html>

Image Optimization Tools

Build-Time Optimization

Command-line tools:

  • ImageMagick - Convert and resize
  • ffmpeg - Video thumbnails
  • Sharp (Node.js) - Automated processing
  • Squoosh CLI - Modern format conversion
# Convert to WebP
cwebp input.jpg -o output.webp -q 80

# Convert to AVIF
avifenc input.jpg output.avif -s 2

# Resize with ImageMagick
convert input.jpg -resize 800x output.jpg

Online Tools

  • Squoosh.app - Google’s web-based optimizer
  • TinyPNG - PNG and JPEG compression
  • Cloudinary - CDN with automatic optimization
  • ImageOptim - Mac app for compression

Automated Solutions

  • Next.js Image component - Automatic optimization
  • Cloudinary - On-the-fly transformations
  • imgix - Real-time image processing
  • Netlify Large Media - Git-based image optimization

Performance Best Practices

Serve modern formats (AVIF, WebP) with fallbacks ✅ Use srcset and sizes for resolution switching ✅ Lazy load below-the-fold imagesInclude width/height to prevent layout shift ✅ Compress images (aim for 80-85% quality) ✅ Use CDN for faster delivery ✅ Set proper cache headersConsider image CDNs for automatic optimization

Common Mistakes

Single large image for all devicesNot compressing imagesLazy loading hero imagesMissing width/height causing layout shiftOnly using JPEG (miss WebP/AVIF savings) ❌ Not testing on slow connectionsForgetting alt textOver-optimizing (too low quality)

Responsive Images Checklist

  • ✅ Multiple image sizes generated (400, 800, 1200, 1600px)
  • ✅ Modern formats provided (AVIF, WebP)
  • ✅ srcset attribute with width descriptors
  • ✅ sizes attribute with appropriate breakpoints
  • ✅ Alt text for all images
  • ✅ Width and height attributes set
  • ✅ Lazy loading for below-fold images
  • ✅ Compressed with appropriate quality
  • ✅ Tested on various devices and connections

Testing Responsive Images

Browser DevTools

  1. Open DevTools Network tab
  2. Check which image size loads
  3. Test different viewport sizes
  4. Throttle network speed
  5. Verify format (WebP/AVIF vs JPEG)

Lighthouse Audit

Run Lighthouse to check:

  • Properly sized images
  • Modern image formats
  • Offscreen images deferred
  • Image compression

WebPageTest

Test with WebPageTest.org to see:

  • Image download times
  • Total image bytes
  • Optimization opportunities

Future-Proof Strategies

Use Picture for Maximum Flexibility

<picture>
  <!-- Future format -->
  <source type="image/jxl" srcset="image.jxl">
  
  <!-- Current best -->
  <source type="image/avif" srcset="image.avif">
  
  <!-- Widely supported -->
  <source type="image/webp" srcset="image.webp">
  
  <!-- Universal fallback -->
  <img src="image.jpg" alt="Description">
</picture>

Embrace Automation

Don’t manually create all image sizes. Use:

  • Build tools (webpack, Vite, Next.js)
  • Image CDNs (Cloudinary, imgix)
  • CMS with automatic resizing

Keep Learning

Try responsive images in the htmlEditor.net playground today!

Responsive images are no longer optional—they’re essential for modern web development. Master srcset, sizes, and the picture element, and your users will enjoy faster, better experiences on every device.

← Back to all blog posts

    Share: