Responsive images: srcset, sizes and <picture> explained

Stop shipping a 4000-pixel image to a 390-pixel phone. srcset, sizes and the <picture> element are the browser-native way to serve the right file to the right screen — no JavaScript required.

The problem srcset solves

A single src attribute gives every device the same file. Phones download a desktop-sized image and scale it down; desktops get a mobile-sized image that looks soft. Both cases waste bandwidth and hurt LCP.

srcset with width descriptors

List the same image at several widths and let the browser choose:

The browser knows its viewport width, pixel density and network conditions, and picks the best candidate from that list. Rule of thumb: generate widths at 320, 640, 960, 1280, 1920 and 2560px and stop where your layout's widest column ends.

The sizes attribute

The sizes attribute tells the browser how wide the image will actually be displayed, so it doesn't have to guess. Without it, the browser assumes the image spans the full viewport width and downloads something too large.

Write it as a media-condition list: sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw". Getting sizes right is the difference between srcset working and srcset quietly wasting data.

The <picture> element and art direction

Use <picture> for two things. First, format negotiation — serve AVIF to browsers that accept it, WebP next, JPEG as fallback. Second, art direction — a cropped, tighter version of a hero image on mobile instead of the same wide image shrunk down.

The final <img> inside <picture> is mandatory: it's the fallback, and it's what carries alt, width, height and loading behavior.

Common mistakes

Forgetting sizes (srcset then over-downloads); putting loading="lazy" on the LCP image; omitting width and height (causes CLS); generating widths far beyond your layout's actual maximum; and using <picture> media queries when a simple srcset would do.

Compress your images now — free and private

Drop your files and ImageAlchemy compresses them in your browser. No uploads, no accounts, no limits. Batch process hundreds at once and download a ZIP.

Open the compressor
100% private No signup

Frequently asked questions

srcset lets you list multiple versions of the same image at different widths (or pixel densities). The browser picks the best one for the current viewport, pixel ratio and network conditions, so phones get small files and desktops get sharp ones.

It tells the browser how wide the image will be displayed, in CSS pixels, at various breakpoints. Without it the browser assumes the image fills the viewport width and downloads a file larger than needed. Always provide sizes when using width descriptors in srcset.

Use <picture> when you need format negotiation (serve AVIF, fall back to WebP then JPEG) or art direction (different crops or entirely different images at different screen sizes). For a single image at multiple widths, srcset with width descriptors is enough.

Typically 4–6 widths spanning your layout's actual range: e.g. 320, 640, 960, 1280 and 1920px. Don't generate widths wider than the largest column the image will ever occupy — that wastes generation time and storage for files nobody downloads.

Yes. Serving correctly sized images reduces downloaded bytes, which improves LCP and other Core Web Vitals metrics that Google uses as ranking signals. Google also recommends responsive images directly in its image SEO and Core Web Vitals documentation.