Skip to content
Platform internals & deliveryLesson 4 of 4Intermediate12 min

Responsive images

srcset and sizes let the browser fetch the smallest sharp source; modern formats and reserved dimensions cut bytes and layout shift for better Core Web Vitals.

Kept on this device only.

In one line: ship several sizes of an image and a sizes hint, and the browser fetches the smallest one that still looks sharp — in a modern format, in a box whose dimensions are reserved so the page never jumps.

What it is

Images are usually the heaviest thing on a page, and the easiest to get wrong: a single 1200px JPEG sent to a 360px phone wastes most of its bytes, and an image with no declared size shoves the layout down when it finally loads.

Responsive images fix both. srcset offers the browser a set of sources at different widths; sizes tells it how wide the image will render; and the browser picks the smallest source that's still crisp at the device's resolution. Pair that with a modern format (AVIF, then WebP, then a JPEG fallback) and reserved dimensions, and you cut bytes dramatically while keeping the layout stable.

Why it matters

This is among the highest-leverage performance work you can do, and it maps straight onto Core Web Vitals. The hero image is usually the Largest Contentful Paint element, so shrinking it and prioritising its fetch directly improves LCP. Declaring width/height (or aspect-ratio) reserves the box before load, which is how you avoid Cumulative Layout Shift — the jarring jump when an image pops in and pushes everything down.

AVIF and WebP routinely cut file size 30–50% over JPEG at equal quality, so the format choice alone can halve your image payload.

See it

Live demo
Tweak it2
640
Scrub the viewport and watch srcset pick the smallest sharp source; aspect-ratio holds the box.

Scrub the viewport width and watch which srcset candidate the browser would choose — narrower screens pull a smaller file. Switch the format to see the source name change. The box keeps its 16:9 ratio the whole time, reserved by aspect-ratio.

How it works

The browser does the selection, given good hints:

  • srcset with width descriptorshero-400.avif 400w, hero-800.avif 800w, hero-1200.avif 1200w declares each source and its intrinsic width.
  • sizes — tells the browser the image's rendered width at different breakpoints (sizes="(min-width: 60rem) 50vw, 100vw") so it can choose before layout. Get this wrong and it over- or under-fetches.
  • <picture> + <source type> — offer AVIF first, WebP next, and a plain <img> JPEG as the universal fallback; the browser takes the first type it supports.
  • Reserved box — set width/height attributes (or CSS aspect-ratio) so space is held before the bytes arrive — no CLS.
  • Priority hintsfetchpriority="high" on the LCP image, loading="lazy" on below-the-fold ones.

Build it

HTML
A responsive hero: modern formats, width descriptors, reserved box
<picture>
  <source
    type="image/avif"
    srcset="hero-400.avif 400w, hero-800.avif 800w, hero-1200.avif 1200w"
    sizes="(min-width: 60rem) 50vw, 100vw" />
  <source
    type="image/webp"
    srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
    sizes="(min-width: 60rem) 50vw, 100vw" />
  <img
    src="hero-800.jpg"
    srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
    sizes="(min-width: 60rem) 50vw, 100vw"
    width="1200" height="675"
    fetchpriority="high"
    alt="Quarterly sales dashboard showing an upward trend" />
</picture>

Make it yours

Use the controls beside the demo above to change viewport width and format — each change updates the example live.

Experiment in the playground
  • Drag the viewport down to mobile widths — the browser drops to the 400w source, sending a fraction of the bytes.
  • Switch the format to JPEG and back: same markup shape, but AVIF is typically half the size for the same picture.
  • The preview box never resizes as the source changes — that fixed aspect-ratio is exactly what keeps CLS at zero.

Reproduce it with an LLM

Reproduce it with an LLM

You are a senior front-end engineer focused on Core Web Vitals. Produce a responsive `<img>` for a hero image: a `srcset` of width descriptors (400w/800w/1200w), a `sizes` attribute that matches the layout, AVIF with a WebP and JPEG fallback via `<picture>` and `<source type>`, explicit `width`/`height` (or `aspect-ratio`) to reserve the box and prevent layout shift (CLS), meaningful `alt` text, and `fetchpriority="high"` on the LCP image while lazy-loading below-the-fold ones. Briefly explain how the browser uses `srcset`/`sizes` to pick a source. Return only the HTML (and any small CSS).

Pitfalls & accessibility

Further reading