How to Fix Non Responsive Images with the Right HTML
A markup focused guide to srcset, sizes, and the picture element so phones stop downloading desktop images and every device gets the right file.

On this page
Responsive image markup is one of those things that looks simple and hides a lot of mistakes. Write srcset but leave out sizes, and the browser downloads the largest file on every phone. Use picture when you only needed srcset, and you add complexity with no benefit. This guide focuses on the markup itself, so every device ends up with a file that actually fits its screen.
If you have not yet trimmed image weight in general, start with our broader checklist at slow images. This page picks up where step four of that guide leaves off. For format choices, see large PNG images.
If you build in Webflow, Framer, or a similar visual tool, the builder usually writes srcset and sizes for you automatically when you drop in an image. Your job is upstream, upload source files at the largest width you will actually display so the platform has enough resolution to generate every size variant. If your builder's generated markup is wrong or missing sizes, the same rules below apply when you override the embed with custom HTML.
Step 1: Generate the right set of widths
Pick widths that match the breakpoints your layout uses in practice. A typical set looks like 480, 960, and 1920 pixels, with an extra 2880 or 3840 for retina displays. More widths give the browser more options but also mean more build work.
Use Sharp (a Node image processing library), ImageMagick (a command-line image tool), or your framework's built-in image tooling to produce each width. Keep filenames predictable so srcset reads cleanly:
hero-480.webp
hero-960.webp
hero-1920.webp
Step 2: Write srcset with correct descriptors
srcset lists your widths with a descriptor that tells the browser the real pixel width of each file. Use the w descriptor, not x, for the common case where you care about device width rather than pixel density.
<img
src="/img/hero-960.webp"
srcset="/img/hero-480.webp 480w,
/img/hero-960.webp 960w,
/img/hero-1920.webp 1920w"
alt="..."
/>
The src attribute is a fallback for browsers that do not support srcset, which in 2026 means almost no one. Still, keep it. The MDN img reference has the full attribute table if you want the edge cases.
Step 3: Write a sizes attribute that matches your layout
Without sizes, the browser assumes the image will fill the full viewport and downloads the widest file that fits. That is almost never what you want. sizes tells the browser how wide the image actually renders at each breakpoint.
<img
src="/img/hero-960.webp"
srcset="/img/hero-480.webp 480w,
/img/hero-960.webp 960w,
/img/hero-1920.webp 1920w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
960px"
alt="..."
/>
Read sizes in order. On a phone up to 600 pixels wide, the image takes the full viewport. Up to 1200 pixels it takes half the viewport. Above that, it renders at a fixed 960 pixels. The browser picks the smallest file that still covers the rendered size at the current device pixel ratio. web.dev's responsive images course walks through the logic with diagrams.
Step 4: Use picture for art direction and format fallbacks
The picture element lets you swap in different images at different breakpoints, or serve different formats with fallbacks. It wraps one or more source elements and a final img that acts as the default.
<picture>
<source type="image/avif" srcset="/img/hero.avif" />
<source type="image/webp" srcset="/img/hero.webp" />
<img src="/img/hero.jpg" alt="..." />
</picture>
For art direction, add media attributes to the source tags so mobile gets a tightly cropped version and desktop gets the wide shot. The MDN picture reference covers both patterns.
Step 5: Verify the browser picks the right file
Open your page on a phone and a desktop with the Network tab open. Check which image URL the browser actually downloaded for each. On the phone, you should see the smallest or second smallest file. On the desktop, you should see the largest. If the phone is still pulling the full size, your sizes attribute is wrong and needs another pass.
Paste your URL into our Website Optimizer to get an automated check across every image on the page. We flag images with no srcset, no sizes, or mismatched widths, so you can fix the markup before it ships. For whole-site audits, our Heavy Asset Finder does the same check page by page.