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
- The browser reads
sizesto determine how wide the image will be displayed - It checks the device pixel ratio (1x, 2x, 3x)
- It picks the smallest image from
srcsetthat 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
widthandheightto prevent layout shifts (CLS)
Image Optimization Workflow
- Resize — Use our Image Resizer to create multiple sizes
- Compress — Use our Image Compressor at 80-85% quality
- Convert — Use our Image to WebP for modern format
- Generate favicons — Use our Favicon Generator
- 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
- Image Resizer — Create multiple image sizes
- Image Compressor — Optimize file size
- Image to WebP — Convert to modern format
- Aspect Ratio Calculator — Calculate dimensions
- Favicon Generator — Generate all favicon sizes
- Meta Tag Generator — OG image tags
responsive imagessrcsetsizes attributepicture elementlazy loadingimage optimizationweb performance