A laptop on a desk displaying a product website layout
Responsive Design

Responsive Images Done Right: Mastering srcset, sizes, and the picture Element

WebPMagic Avatar WebPMagic Editorial
10 Min Read

Converting an image to WebP is only half the job. If you then serve that same 1600-pixel-wide file to a phone, a tablet, and a 4K monitor alike, you are still wasting megabytes on the devices that can never display them. Responsive images solve this by handing the browser a menu of files and letting it download exactly the right one. Master three tools — srcset, sizes, and <picture> — and you will never over-serve an image again.

Key Takeaways

  • Use srcset with w descriptors to offer multiple widths of the same image.
  • The sizes attribute tells the browser how wide the image will display, so it can choose correctly.
  • Use x descriptors for fixed-size images that only need to handle screen density.
  • Reach for <picture> when you need art direction (different crops) or multiple file formats.

The Problem with One Fixed Image

A single <img src="photo.jpg"> forces every visitor to download the identical file. To look sharp on a high-resolution laptop, that file has to be large — but a phone on a cellular connection then pays the same penalty for pixels it cannot even render. The result is slow loads, blown data budgets, and a worse Largest Contentful Paint on exactly the mobile devices Google weights most heavily.

Resolution Switching with srcset and w Descriptors

The most common need is "same image, different sizes." You export the image at several widths, then list them in srcset with a w descriptor stating each file's intrinsic pixel width.

<img
  src="photo-800.webp"
  srcset="photo-400.webp   400w,
          photo-800.webp   800w,
          photo-1200.webp 1200w,
          photo-1600.webp 1600w"
  sizes="(max-width: 600px) 100vw, 50vw"
  alt="Hot air balloons over a valley"
  width="1200"
  height="800"
  loading="lazy"
>

The src still matters as a fallback for browsers that do not understand srcset. The w values describe each candidate; the browser combines them with the sizes hint and the device's pixel density to pick one file.

The sizes Attribute: The Part Everyone Forgets

Here is the crucial subtlety: when the browser begins choosing an image, it has often not yet calculated your CSS layout. It does not know that your image will render at half the viewport width. The sizes attribute is how you tell it in advance.

Read sizes="(max-width: 600px) 100vw, 50vw" as: "If the viewport is 600px or narrower, this image fills 100% of the viewport width; otherwise it occupies 50%." The browser multiplies that display width by the device pixel ratio to find the ideal source. Omit sizes and the browser assumes 100vw, frequently downloading a file far larger than needed.

Keep sizes honest

Your sizes value must reflect your actual CSS. If a redesign changes a column from 50% to 33% of the page, update sizes too — otherwise the browser keeps fetching oversized images and your savings quietly evaporate.

Density Switching with x Descriptors

Sometimes an image renders at a single fixed size — an avatar, an icon, a logo — and the only variable is screen density. For these, the simpler x descriptor is perfect. No sizes attribute is required.

<!-- A 100x100 avatar that stays crisp on retina screens -->
<img
  src="avatar-100.webp"
  srcset="avatar-100.webp 1x,
          avatar-200.webp 2x,
          avatar-300.webp 3x"
  alt="User profile photo"
  width="100"
  height="100"
>

Art Direction with the picture Element

Resolution switching always serves the same image, just scaled. But what if a wide desktop hero looks terrible when squeezed onto a phone, and you would rather show a tighter, portrait crop? That is art direction, and it is the job of <picture> with media conditions.

<picture>
  <!-- Narrow screens get a tighter, taller crop -->
  <source media="(max-width: 600px)" srcset="hero-portrait.webp">

  <!-- Wider screens get the full landscape shot -->
  <source media="(min-width: 601px)" srcset="hero-landscape.webp">

  <img src="hero-landscape.webp" alt="Team collaborating in an office"
       width="1200" height="600">
</picture>

Combining Formats and Responsiveness

The two techniques compose beautifully. You can nest srcset and sizes inside the sources of a <picture> to deliver both the right format and the right resolution at once — AVIF or WebP for capable browsers, scaled to the exact device width, with a JPEG safety net.

<picture>
  <source
    type="image/webp"
    srcset="photo-800.webp 800w, photo-1600.webp 1600w"
    sizes="(max-width: 600px) 100vw, 50vw">
  <img
    src="photo-800.jpg"
    srcset="photo-800.jpg 800w, photo-1600.jpg 1600w"
    sizes="(max-width: 600px) 100vw, 50vw"
    alt="Coastline at golden hour"
    width="1600" height="900" loading="lazy">
</picture>

Common Mistakes to Avoid

  • Forgetting sizes with w descriptors — the browser defaults to 100vw and over-downloads.
  • Omitting width and height — you reintroduce layout shift even with perfect responsive sources.
  • Lazy-loading the LCP image — your above-the-fold hero should load eagerly, responsive or not.
  • Too many breakpoints — three or four well-chosen widths cover almost every device; a dozen just bloats your build.

Responsive images reward a little upfront effort with dramatic, device-specific savings. Pair them with a modern format and explicit dimensions, and you have the complete recipe for images that are fast everywhere and stable on every screen.

Generate your responsive widths

Every entry in a srcset should be an optimized WebP. Resize and convert each width in seconds with our free, browser-based optimizer — your files never leave your device.

Optimize Images Now
WebPMagic Editorial

About WebPMagic

WebPMagic is an independent project focused on image optimization and web performance. These guides are researched and edited to give developers clear, practical, and accurate information for building faster websites, with tips drawn from hands-on use of our own WebP conversion tool. Found an error or have a suggestion? Let us know via our contact page.