Topic 5.1
Responsive Images
In one line
With srcset, sizes and <picture> you list several versions of an image and let the browser download only the one that fits the screen, instead of sending a huge photo to every phone.
Think of it like this
Buying shoes. You don't buy the biggest pair in the shop and hope they fit; you tell the shopkeeper your size and get the pair that fits. With responsive images, the page tells the browser which sizes exist, the browser knows its own screen, and it fetches the pair that fits.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Responsive image
- An image that downloads and shows a version suited to the screen it's on.
- srcset
- An
img(orsource) attribute listing several image files the browser may choose from. - w descriptor
- A number with
wafter a file insrcset, like800w: the file's real width in pixels. - x descriptor
- A number with
xafter a file insrcset, like2x: the screen density the file is made for. - sizes
- An attribute that tells the browser how wide the image will be shown on the page, so it can choose a file before CSS loads.
- Viewport
- The visible part of the browser window.
100vwmeans its full width. - Device pixel ratio (DPR)
- How many physical screen dots make up one CSS pixel. Sharp phone screens are often 2 or 3.
- picture
- An element holding several
sourceoptions and oneimg. The first matching source is used. - Art direction
- Showing a different crop or picture on different screen sizes, not only a different size of the same picture.
Step by step
01Start with one image
A plain <img> always downloads the same file, whatever the screen. This 1600px photo costs a phone just as much as a desktop.
<img src="cat-1600.jpg" alt="A ginger cat asleep on a windowsill" width="1600" height="900">02List the versions with srcset
Export the same picture at a few widths (an image tool or a build step does this) and list them with their real widths. Keep src as the fallback.
On its own, srcset with w makes the browser assume the image is as wide as the viewport (sizes defaults to 100vw).
<img src="cat-800.jpg"
srcset="cat-400.jpg 400w, cat-800.jpg 800w, cat-1600.jpg 1600w"
alt="A ginger cat asleep on a windowsill" width="1600" height="900">03Say how wide it will be with sizes
In this layout the image fills the screen on phones and takes a third of the width in a three-column grid on wide screens. sizes describes exactly that, so the browser can choose before it has downloaded the CSS.
Values in sizes can be vw, px, em or calc(), but not percentages: the browser hasn't done layout yet, so it doesn't know what 50% of the parent is.
<img src="cat-800.jpg"
srcset="cat-400.jpg 400w, cat-800.jpg 800w, cat-1600.jpg 1600w"
sizes="(max-width: 700px) 100vw, 33vw"
alt="A ginger cat asleep on a windowsill" width="1600" height="900">04Watch the browser do the maths
On a phone 390px wide with DPR 3: the slot is 100vw = 390px, times 3 = 1170 real pixels needed. The smallest file at least that wide is cat-1600.jpg.
On a laptop 1440px wide with DPR 1: the slot is 33vw ≈ 475px, times 1 = 475. The browser picks cat-800.jpg, the smallest file that covers it. The big file is never downloaded.
05Fixed-size images use x descriptors
A logo is always 160px wide, so the layout never changes its size. Only the screen density matters, which is what x describes. No sizes needed.
<img src="logo-160.png" srcset="logo-160.png 1x, logo-320.png 2x, logo-480.png 3x"
alt="Hectal" width="160" height="40">06Change the picture itself with <picture>
Art direction: on wide screens show the whole scene; on narrow screens show a close crop, so the cat isn't a tiny dot. Each <source> can have its own srcset and sizes. The <img> comes last and is required.
type lets you offer modern formats: a browser that can't decode AVIF skips that source and moves to the next one.
<picture>
<source media="(min-width: 800px)" srcset="scene-wide.avif" type="image/avif">
<source media="(min-width: 800px)" srcset="scene-wide.jpg">
<source srcset="cat-closeup.avif" type="image/avif">
<img src="cat-closeup.jpg" alt="A ginger cat asleep on a windowsill" width="800" height="800">
</picture>Try it yourself
- 1
Predict the pick
Before running the first example, look at the info line under the preview: your viewport width and DPR. Work out slot width × DPR yourself, then press Run. Did the browser pick the file you predicted?
- 2
Change sizes
In the first example, change
sizesto100px. Predict: the slot is now tiny, so the browser should pick the400wfile. Run it and check. (If it still shows a bigger file, the browser reused one from its cache, which the spec allows. Reload the page and try again.) - 3
Remove the media condition
In the
pictureexample, deletemedia="(min-width: 500px)"from the second source. Now it matches everywhere: which picture do you predict on a narrow preview?
Code & diagrams
The pictures are small SVG images written into the code (data URIs) so this works offline. Which one you get depends on your screen, so your console may differ from someone else's.
Preview
Console
Nothing logged yet.The first source is skipped because no browser knows the type `image/x-future`. Then a narrow preview shows the close-up and a wide one shows the wide crop. Drag the preview wider or narrower and press Run.
Preview
Console
Nothing logged yet.With x descriptors the shown size comes from `width` (or the 1x file), whatever file is downloaded. A 2x file is drawn at half its pixel size, so it looks sharp, not big.
Preview
Console
Nothing logged yet.Expected console output
Candidates in srcset: 2
sizes attribute: ""
Has x descriptors: true
Shown width in CSS pixels: 160Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Use w descriptors without sizes
Remove the sizes attribute from an image that is shown at 300px wide in a sidebar, on a 1440px laptop.
Break #2
Forget the img inside picture
Write a <picture> with two <source> elements and no <img>.
Myth vs fact
Myth
The browser picks the image from my CSS width.
Fact
It picks from sizes, often before your CSS has even arrived. If sizes and your CSS disagree, the browser downloads the wrong file and CSS then scales it.
Myth
srcset makes the image look different on phones.
Fact
srcset is for different sizes of the same picture. To show a different crop or a different picture, use <picture> with media (art direction).
Myth
Bigger files always look better on retina screens.
Fact
Past about 2x the eye barely sees the difference. Many sites cap at 2x to save bytes, even on DPR-3 phones.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Image selection happens in the preload scanner, a fast pass over the HTML that starts downloads before the main parser and before CSS. That's why
sizesexists at all: the browser has no layout information yet. - ▸
Chromium supports
sizes="auto"forloading="lazy"images: since a lazy image is fetched after layout, the browser can use its real rendered width. Other browsers are still adding it; keep an explicit fallback such assizes="auto, (max-width: 700px) 100vw, 33vw". - ▸
Inside
<picture>,<source>can carry its ownwidthandheightattributes, so art-directed crops with different aspect ratios still reserve the right space (see Topic 5.2). - ▸
Image CDNs and frameworks (for example
next/image) generate thesrcsetwidths for you. You still need to give a correctsizes; it is the part tools can't guess.
Remember this
- 1
A responsive image is an image that adapts to the screen it is shown on. The problem it solves: one 2400-pixel-wide photo looks sharp on a big monitor, but a phone that shows it 400 pixels wide still downloads every byte. That wastes data, battery and time. The fix is to make several versions of the same picture (for example 400, 800 and 1600 pixels wide) and let the browser choose.
- 2
srcsetwith w descriptors lists the versions and their real widths in pixels:srcset="cat-400.jpg 400w, cat-800.jpg 800w, cat-1600.jpg 1600w". Thewmeans "this file is this many pixels wide". You describe the files; the browser does the maths. The plainsrcstays as the fallback for very old browsers and as the default. - 3
sizestells the browser how wide the image will be on the page, before any CSS has loaded:sizes="(max-width: 600px) 100vw, 50vw"means "on screens up to 600px wide the image fills the whole viewport width (100vw); otherwise it takes half (50vw)". A viewport is the visible area of the browser window, and1vwis 1% of its width. The browser reads the conditions left to right and uses the first one that matches; the last value has no condition and is the default. Withoutsizes, the browser assumes100vw. - 4
The browser then multiplies: slot width × device pixel ratio (DPR, how many physical screen dots make one CSS pixel: 1 on many laptops, 2 or 3 on phones). A 400px slot on a DPR-2 phone needs about 800 real pixels, so it picks
cat-800.jpg. The spec lets the browser decide the final choice: on a slow connection it may pick a smaller file, and if a larger version is already in its cache it may reuse that. - 5
x descriptors are the simpler form for images shown at a fixed size, like a 200px logo:
srcset="logo.png 1x, logo@2x.png 2x". The browser picks by DPR alone. Usexfor fixed-size images andw+sizesfor images whose width changes with the layout. You can't mixxandwin onesrcset. - 6
<picture>wraps several<source>elements and one<img>. The browser checks each<source>from the top and uses the first one that matches itsmediacondition and/or itstype(file format). That gives you art direction: showing a different crop on phones (a close-up of a face) and on desktops (the wide scene). It also lets you offer a modern format such as AVIF with a JPEG fallback. The<img>inside is required: it is what is actually shown, and itsalt,width,heightand CSS apply whichever file wins.
Explain it without notes
What problem do srcset and sizes solve, and how does the browser use them to choose a file?
When would you use x descriptors and when w descriptors?
What is the difference between srcset resolution switching and <picture> art direction?
Why can't sizes use percentages?
Practice
Write an <img> for a hero banner that fills the full width on every screen, with files hero-640.jpg, hero-1280.jpg and hero-1920.jpg.
Write a <picture> that offers photo.avif and photo.webp before a photo.jpg fallback.
A product image is 100% wide below 600px, 50% wide up to 1000px, and a fixed 400px above that. Write its sizes.
Trade-offs
- ↔
More versions in
srcsetmeans better-fitting downloads but more files to generate, store and cache; three to five widths is a common balance. - ↔
Art direction gives the best picture per screen but means designing and maintaining several crops; use it only where a single image really doesn't work small.
Done when you can
I can write
srcsetwith w descriptors and a matchingsizes.I can work out which file a browser will pick from slot width and DPR.
I know when to use x descriptors instead.
I can use
<picture>for art direction and modern formats with a fallback<img>.I can check which file was downloaded with
currentSrcor the Network panel.