urltoolskit.org
URL utilities, in the browser
Say hi →

srcset builder

one URL pattern → srcset · complete <img> · <picture> with AVIF and WebP

Every image CDN takes a width in the URL, so a responsive srcset is the same URL repeated with different numbers — tedious to write and easy to typo. Put {w} where the width goes, list your widths, and get the srcset, a complete <img> tag, and a <picture> element with modern formats.

Ready.

How to use

  1. Paste your image URL and replace the width value with {w}. Cloudinary, imgix, Cloudflare Images, Shopify, WordPress and Next.js image URLs all have one.
  2. List the widths you actually generate. Five is plenty; more candidates mean more cache entries for a smaller gain.
  3. Keep Descriptor on width for anything that changes size with the viewport. Use density only for images displayed at a fixed CSS size, like an avatar or a logo.
  4. Fill in sizes — this is the part that is usually wrong, and the status line warns when it is missing.
  5. Copy the <img> tag. It already carries loading="lazy" and decoding="async".

sizes is where responsive images go wrong

With w descriptors, the browser picks a candidate before it has laid the page out, so it cannot know how wide your image will be. sizes is you telling it in advance. Leave it out and the default is 100vw — the browser assumes the image spans the whole viewport and downloads the largest candidate, which is precisely the download you were trying to avoid.

sizes is a list of media conditions with the width the image will occupy when each matches, ending with a bare fallback: (max-width: 700px) 100vw, (max-width: 1200px) 50vw, 600px means full width on phones, half on tablets, and a fixed 600 pixels above that. The values must match your CSS — if the CSS says the image is 600px and sizes says 100vw, the browser downloads a needlessly large file on every load, and no audit tool will flag it as a bug.

On the <picture> output: it is only worth using when you are serving different formats or genuinely different crops per breakpoint. For the ordinary case of one image at several sizes, a plain <img> with srcset and sizes is simpler and does the same job — the browser's own format negotiation via Accept headers handles AVIF and WebP on most CDNs without any markup at all. Note that the source order matters: browsers take the first <source> they support, so AVIF must come before WebP.

FAQ

Which widths should I pick?

Work back from the largest size the image is ever displayed at, doubled for high-density screens, then step down in roughly 1.5× increments. For a 700px content column that is about 400, 700, 1000, 1400 — there is no value in a 2400px candidate for an image that never renders wider than 700 CSS pixels.

Can I mix w and x descriptors?

No — the spec forbids it in one srcset, and browsers ignore the whole attribute if you do. Pick the one that matches how the image is sized.

What does {h} do?

It expands to a 16:9 height for the width on that row, for CDNs that want both dimensions. If your aspect ratio is different, put the height in literally or use the CDN's aspect-ratio parameter instead.

Should the first image on the page be lazy-loaded?

No — remove loading="lazy" from anything above the fold and add fetchpriority="high" instead. Lazy-loading your largest contentful paint image delays it measurably, which is one of the more common self-inflicted performance problems.