DTTooleras

Responsive Images: srcset, sizes, and the picture Element Explained

A practical guide to responsive images — srcset for resolution switching, sizes for viewport-based selection, the picture element for art direction, and lazy loading for performance.

DevToolsHub Team18 min read478 words

Why Responsive Images Matter

A single hero image can be 500KB as a 2000px JPEG. On a mobile phone with a 375px viewport, you are wasting 80% of that bandwidth. Responsive images serve the right size to the right device.

The srcset Attribute

srcset tells the browser about available image sizes:

<img
  src="photo-800.jpg"
  srcset="
    photo-400.jpg 400w,
    photo-800.jpg 800w,
    photo-1200.jpg 1200w,
    photo-1600.jpg 1600w
  "
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
  alt="A beautiful landscape"
  width="1600"
  height="900"
  loading="lazy"
/>

How the Browser Chooses

  1. The browser reads sizes to determine how wide the image will be displayed
  2. It checks the device pixel ratio (1x, 2x, 3x)
  3. It picks the smallest image from srcset that covers the display size

For a 375px phone at 2x DPR with sizes="100vw":

  • Display width: 375px
  • Needed pixels: 375 × 2 = 750px
  • Browser picks: photo-800.jpg (closest match above 750)

The sizes Attribute

sizes tells the browser how wide the image will be at different viewport widths:

sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"

This means:

  • Below 600px viewport: image is 100% of viewport width
  • 600-1200px viewport: image is 50% of viewport width
  • Above 1200px: image is 33% of viewport width

The picture Element

Use <picture> for art direction (different crops) or format selection:

<!-- Format selection (serve modern formats with fallback) -->
<picture>
  <source srcset="photo.avif" type="image/avif" />
  <source srcset="photo.webp" type="image/webp" />
  <img src="photo.jpg" alt="Photo" width="1200" height="800" />
</picture>

<!-- Art direction (different crops for different screens) -->
<picture>
  <source media="(max-width: 600px)" srcset="photo-mobile.jpg" />
  <source media="(max-width: 1200px)" srcset="photo-tablet.jpg" />
  <img src="photo-desktop.jpg" alt="Photo" width="1200" height="800" />
</picture>

Lazy Loading

<!-- Native lazy loading -->
<img src="photo.jpg" loading="lazy" alt="Photo" width="800" height="600" />

<!-- Eager loading for above-the-fold images -->
<img src="hero.jpg" loading="eager" fetchpriority="high" alt="Hero" width="1200" height="600" />

Rules:

  • Use loading="lazy" for all images below the fold
  • Use loading="eager" + fetchpriority="high" for the LCP image
  • Always include width and height to prevent layout shifts (CLS)

Image Optimization Workflow

  1. Resize — Use our Image Resizer to create multiple sizes
  2. Compress — Use our Image Compressor at 80-85% quality
  3. Convert — Use our Image to WebP for modern format
  4. Generate favicons — Use our Favicon Generator
  5. Check aspect ratio — Use our Aspect Ratio Calculator

Next.js Image Component

import Image from "next/image";

<Image
  src="/photo.jpg"
  alt="Description"
  width={1200}
  height={800}
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
  quality={85}
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,..."
/>

Next.js automatically generates srcset, serves WebP/AVIF, and optimizes images.

Related Tools

responsive imagessrcsetsizes attributepicture elementlazy loadingimage optimizationweb performance

Related articles

All articles

Practice with free tools

200+ free developer tools that run in your browser.

Browse all tools →