LUCKY.GRAPHICS
guides

Responsive Images: srcset, sizes, and Picture Without the Guesswork

How the browser picks an image file: width descriptors, the sizes slot, pixel ratio, art direction with picture, and a worked sizing worksheet with checklist.

Lucky Graphics EditorialOctober 4, 202616 min

Responsive Images: srcset, sizes, and Picture Without the Guesswork

Most image weight on the web is not a compression problem. It is a sizing problem. A phone downloads a desktop-sized hero, renders it in a slot a quarter as wide, and throws the extra pixels away. A laptop on a dense display gets the opposite failure: a file that is too small for the screen, stretched soft by the browser. Both failures come from the same habit, shipping one file at one size and asking every screen to cope.

Responsive images fix that habit without any JavaScript and without a redesign. You export the same image at a few widths, describe those files in markup, and tell the browser how wide the image will actually appear. The browser, which is the only party that knows the screen size, the pixel density, and sometimes the network conditions, picks the closest file. This guide explains how that choice works, how to write the markup by hand when you need to, and how to size a real layout without guessing. It assumes you have already chosen a format; if that decision is still open, the image format decision guide covers SVG, PNG, JPEG, WebP, and AVIF first. Format decides what the file is. This guide decides how big it is.

The Short Answer

  • Same image, different screen sizes: use srcset with width descriptors plus a sizes attribute. This is the default pattern for heroes, article images, cards, and product photos.
  • Different crop or composition at different sizes: use the picture element with media queries. That is art direction, and it is a separate job from resolution switching.
  • Different file formats for different browsers: use picture with type, or let your image pipeline handle format negotiation. The image format guide explains when AVIF earns its keep.
  • A fixed-size slot that never changes width: a single-density and double-density pair with 1x and 2x descriptors is enough. Logos and small interface graphics often live here, though SVG is usually better for both.
  • Never: upload the largest original and rely on CSS to shrink it. CSS changes the display size. It does not change the download size.

The rest of this guide is the reasoning, the arithmetic, and the failure modes behind those five lines.

How the Browser Actually Chooses a File

The selection happens in three steps, and each step maps to one piece of markup you control.

Step 1: work out the slot width. The browser reads your sizes attribute and evaluates it against the current viewport. The result is a single number in CSS pixels: the width the image will occupy on screen right now. If you omit sizes, the browser assumes the image fills the whole viewport width, which is almost never true for a real layout. A missing or wrong sizes is the most common reason responsive images appear to do nothing.

Step 2: multiply by pixel density. The slot width is multiplied by the device pixel ratio. A 400 CSS pixel slot on a standard display needs a 400 pixel image. The same slot on a display with a ratio of 2 needs about 800 pixels to stay sharp, and a ratio of 3 needs about 1,200. The browser does this multiplication itself. You never write the ratio into srcset; you supply the candidates and the browser works out the need.

Step 3: pick the closest candidate that covers the need. From the files listed in srcset, the browser selects a file at or near the required width. The exact algorithm allows some discretion, and browsers may factor in network conditions or data-saving settings, but the practical rule designers can rely on is simple: the browser wants the smallest file that still covers slot width times pixel ratio. Give it sensible steps to choose from and it will choose well. Give it one giant file and it has no choice to make.

Two consequences follow. First, the quality of your sizes value matters more than the number of files you export. A perfect candidate list paired with a slot width that is wrong by half will still download the wrong file on every visit. Second, you cannot test this feature by resizing your desktop browser window alone and watching which file loads, because a browser that has already downloaded a larger file may keep using it for a smaller slot. Test in a fresh profile or with the cache disabled, and check the rendered size against the natural size in your developer tools.

Width Descriptors and Density Descriptors

srcset accepts two kinds of descriptors, and mixing them in one list is invalid. Pick the kind that matches the job.

Width descriptors pair each URL with its pixel width: hero-480.jpg 480w, hero-1080.jpg 1080w. They are the right choice whenever the displayed width changes with the viewport, which is nearly every content image. Width descriptors require a sizes attribute to be useful, because without a slot width the browser cannot convert a file width into a density.

Density descriptors pair each URL with a multiple: logo.png 1x, logo@2x.png 2x. They assume the slot width is fixed and only the sharpness requirement changes. They read well and they are honest for fixed slots, but they collapse the moment a layout goes fluid. A card that is 300 pixels wide on desktop and full width on mobile is not a fixed slot, and density descriptors will serve it the wrong file at one end or the other.

The rule that prevents most confusion: if the width in your layout is expressed in percentages, viewport units, or grid fractions, use width descriptors. If the width is a fixed pixel value at every breakpoint, density descriptors are acceptable. When in doubt, use width descriptors. They degrade gracefully in cases where density descriptors do not.

Writing sizes Without Guessing

The sizes attribute is a small list of media conditions with a fallback. The browser uses the first condition that matches, reading left to right, so the order is part of the meaning. A typical article layout might say: on viewports up to 700 pixels wide the image takes the full content width, and above that it takes a fixed column width. Written plainly, that is one conditional length and one default length.

Three habits make sizes reliable in practice.

Derive it from the layout, not from the image. Open the stylesheet or the design file and find the actual rendered width of the slot at each breakpoint: the container width minus padding, the grid column the image sits in, the card width in the card grid. The PX, REM, and EM guide helps if your layout mixes units, because a sizes value written in the wrong unit is a wrong value with correct syntax. Your measuring tool for this is the rendered page itself, not the export dialog.

Cover the breakpoints the layout actually has. A layout with a single mobile breakpoint needs two entries. A card grid that goes from one column to two to four needs an entry for each range. Every missing range falls through to the next condition or the default, which is how a tablet ends up with a phone-sized slot estimate and a blurry image, or a phone ends up with a desktop estimate and a heavy one.

Keep the default honest. The last value, with no media condition, is what large screens get. If the design caps the content column at a fixed width, the default should be that width, not a viewport percentage. The single most common sizes bug in the wild is a default of full viewport width on a centered column layout, which tells the browser the image is far wider than it will ever render and forces the largest download on the very screens that could have used a mid-sized file.

One subtlety is worth knowing before it costs you an afternoon. The browser evaluates sizes early, often before the full stylesheet has settled, because it wants to start the image download as soon as possible. That early evaluation is a feature for the hero image and a hazard for layouts whose slot width depends on late-loading styles or scripts. The practical defence is the same as the accuracy defence: keep image slots in simple, early-known layout, and give every rendered image an explicit width and height or aspect ratio so the slot exists before the file arrives. That also prevents the page from shifting as images load, which readers experience as the text jumping away mid-sentence.

A Worked Sizing Worksheet

The numbers below are a worked example, constructed for this guide to show the method. The layout is illustrative, not a measurement of any real site. The method transfers to any layout once you substitute your own slot widths.

The layout. A blog article page. On phones the content column spans the viewport with small side padding, so an inline image renders at about 360 CSS pixels wide. On tablets the column is about 640 pixels. On desktop the column is capped at 720 pixels and does not grow further. The hero image is wider than the text column: full width on mobile at about 400 pixels, and a capped 1,200 pixels on desktop.

The need at each density. Multiply each slot by the pixel ratios you intend to serve well. For the inline image: 360 at ratio 1 needs a 360 pixel file, at ratio 2 about 720, at ratio 3 about 1,080. The tablet slot of 640 needs about 640, 1,280, and 1,920. The desktop slot of 720 needs about 720, 1,440, and 2,160. You do not need a separate file for every cell in that table. You need a candidate ladder whose steps land near the needs, because the browser rounds up to the next available step.

The candidate ladder. A sensible ladder for this layout, shared by the inline and hero images where their ranges overlap, might be 480, 768, 1,080, 1,440, and 1,920 pixels wide. Check it against the needs: the phone at ratio 2 needs 720 and gets 768, a small overage. The desktop inline image at ratio 2 needs 1,440 and gets 1,440 exactly. The hero on desktop at ratio 1 needs 1,200 and gets 1,440, which is more overage than ideal but acceptable for a single above-the-fold image. The phone hero at ratio 3 needs about 1,200 and gets 1,440. No cell in the table is left underserved by more than one step, and no cell overshoots by a full doubling. That is what a good ladder looks like: uneven needs, even steps, no drama.

How many variants is enough. Five widths cover this layout. In general, steps that grow by roughly 1.4 to 1.6 times each rung waste the least: each step up costs noticeable bytes, so tiny steps create files nobody selects, and huge steps force big overages. Doubling at every rung is too coarse at the small end and too fine at the large end. Export discipline matters more than the exact ladder: generate variants from the original master at each width, at the quality setting you validated for that format, and never generate a larger variant by enlarging a smaller one. Enlargement invents pixels badly and weighs more than an honest export from the master.

The byte logic, stated carefully. File weight grows with pixel count, but not linearly with width, because compression works on content rather than geometry. Doubling the width roughly quadruples the pixel count, and the encoded size rises by less than that on photographic content and by more on noisy content. That is why this worksheet works in widths rather than promised byte savings: the widths are the variable you control in markup, and the bytes follow from your own encoder on your own images. Measure your top images with your own settings before committing to a ladder; the image format guide shows how a small controlled test settles format and quality questions the same way.

Art Direction With picture

Resolution switching keeps the same composition and changes the file. Art direction changes the composition: a wide cinematic hero on desktop becomes a tighter, taller crop on mobile where the subject would otherwise shrink to a thumbnail in the middle of a banner. The picture element handles this by wrapping several source elements, each with its own media condition and its own srcset, around a fallback img. The browser uses the first source whose media condition matches, and the img inside still carries the alt text and the ultimate fallback file.

Use art direction sparingly and honestly. It earns its complexity when the subject genuinely gets lost at small sizes: group photographs, wide product-in-context shots, infographics with text that must stay legible. It wastes effort when the only change is the file width, which plain srcset already handles with less markup and no duplicate crops to maintain. Every art-directed variant is another export to generate, name, and keep in sync when the master changes, so the maintenance cost is real even when the markup cost looks small.

Two ordering rules keep picture predictable. Put the most specific media conditions first, because the browser stops at the first match and never looks further down the list. And keep the fallback img genuinely usable on its own: it is what older tooling, some email clients, and several content scrapers will see, so its src should be a mid-sized, widely compatible file rather than the largest master.

Loading Behaviour: The Other Half of Performance

Choosing the right bytes is half the job. Asking for them at the right time is the other half, and it interacts with responsive selection in ways that surprise people.

The hero and largest content image should load eagerly and early. It is usually the largest visual element on the page, so its download time is the reader's perceived load time. Give it a high fetch priority and do not lazy-load it. Lazy-loading the hero delays the one image the reader is waiting for, and the browser cannot start the responsive selection until it knows it needs the file.

Below-the-fold images should load lazily. The native lazy loading attribute defers offscreen images until the reader scrolls near them, which keeps the initial download focused on what is visible. Combined with responsive variants, this means a long article only downloads the small files for the images the reader actually reaches, at the sizes that reader's screen needs.

Reserve the space before the file arrives. Width and height attributes, or an aspect ratio in CSS, let the browser hold the slot at the right shape while the image loads. Without them, the slot collapses to zero height and the page reflows when each image lands, pushing text down and misplacing taps. Responsive markup that downloads perfectly and still shifts the layout has done half its job.

Do not preload responsive heroes casually. A preload hint that names one fixed file bypasses the selection you built and forces that file on every screen. If you preload a hero, the hint needs the same responsive attributes as the image itself so the browser can still choose. Most sites are better served by correct markup and a high fetch priority than by a preload that guesses wrong for half their visitors.

Background Images and Other Edge Cases

CSS background images do not participate in srcset selection. Media queries can swap background files at breakpoints, and that works, but the browser treats the image as decoration, downloads it with lower priority, and gives screen readers nothing to describe. The decision rule: if the image carries meaning a reader would miss when it fails to load, it belongs in an img with alt text and responsive markup. If it is pure decoration behind text, a background is acceptable, and the breakpoint swap should mirror the same ladder logic rather than loading the desktop file everywhere.

Two smaller cases round out the picture. Favicons and app icons are fixed slots served at density multiples, and they live outside the content layout entirely. Open Graph and social sharing images are picked up by external platforms that ignore responsive markup, so they should be a single, sensibly sized file at the dimensions those platforms expect, exported from the master like any other delivery copy. Neither case benefits from the full ladder; both suffer when someone reuses the largest website variant out of habit.

Five Mistakes That Keep Happening

  1. Shipping srcset without sizes. The browser assumes a full-viewport slot and downloads a file sized for a screen-filling image. Centered columns with this bug routinely fetch two to four times the pixels the slot will display.
  2. A sizes value copied from another site. Slot widths are properties of your layout. A borrowed value describes someone else's columns and will be wrong at exactly the breakpoints where your layout changes.
  3. Variants generated from the wrong source. Resizing a compressed delivery file compounds its artifacts at every step. Every rung of the ladder comes from the master, in one export pass, at the validated quality setting.
  4. Lazy-loading the hero. The attribute that saves bytes below the fold costs real waiting time above it. One eager, high-priority hero and lazy everything else is the pattern that holds up.
  5. Testing selection in a warm browser. A browser that already holds the large file will not downgrade for a smaller slot, which makes careful markup look broken. Verify in a fresh profile with the network panel open, and compare the natural size of the loaded file against the rendered size on screen.

The Pre-Publish Checklist

Copy this into your project notes for any page that ships content images. It assumes a master file, a chosen format, and a real layout to measure against.

  • Slot widths measured: the rendered width of each image slot recorded at every layout breakpoint, from the page itself rather than the design file alone.
  • Ladder exported from the master: each variant generated from the original at its target width and validated quality, never enlarged from a smaller variant.
  • sizes matches the layout: one entry per breakpoint range plus an honest default, in first-match order, checked against the measured slots.
  • Descriptors consistent: width descriptors throughout for fluid slots, density descriptors only for genuinely fixed slots, never mixed in one list.
  • Art direction justified: any picture crop exists because the subject needs it, with the fallback img useful on its own.
  • Space reserved: width and height or aspect ratio present on every content image so the layout does not shift as files arrive.
  • Loading roles set: hero eager with high fetch priority, below-the-fold images lazy, no fixed-file preload fighting the selection.
  • Selection verified cold: fresh profile, cache disabled, loaded file's natural width compared against rendered width at phone, tablet, and desktop sizes.

FAQ

Do I still need srcset if my site uses an image CDN or framework component?

The tooling changes who writes the markup, not whether the selection happens. A CDN or framework image component that generates variants and emits srcset and sizes for you is doing this guide's work automatically, and that is a good arrangement. What you still own is the input: the rendered slot widths, the candidate ladder, and the loading roles. Automated tooling with a wrong slot width produces wrong files very efficiently, so verify the rendered result the same way the checklist describes.

How many variants should I export per image?

Enough that no common slot-and-density combination overshoots by more than one step or lands undersized. For most content layouts that is four to six widths, growing by roughly half again at each rung. More variants than that mostly add build time and storage for files few screens select. Fewer than three usually leaves phones or dense displays badly served at one end of the range.

What happens if my sizes value is slightly wrong?

The browser follows it faithfully, so a slot estimate that is too large downloads a heavier file than needed and one that is too small risks a soft image on dense displays. Small errors cost small overages, which is why measuring the real layout matters more than perfecting the third significant figure. Review sizes whenever the layout changes; a column that gets wider in a redesign silently invalidates the old value.

Should icons and logos use responsive images too?

Usually not in raster form at all. Icons and logos are vector-shaped jobs, and a single SVG scales to every slot and density with no selection logic. The free icons guide covers choosing an icon set, and the icon design principles guide covers the grid discipline behind them. Reserve density-descriptor pairs for the fixed raster cases that genuinely cannot be vector.

Does responsive markup help images inside articles written in Markdown?

Yes, as long as the final HTML carries the attributes. Many site pipelines expand a plain image tag into a responsive picture at build time; others emit only what the author wrote. Check the served HTML for one article image after your next publish: if srcset and sizes are absent, the pipeline needs a step added, because no browser can select variants it was never told about.

Can I use CSS media queries instead of all this?

For decorative backgrounds, yes, with the caveats in the background section above. For content images, the markup approach is stronger: the browser can start the right download earlier, before layout settles, and the image stays meaningful to assistive technology and to any tool that reads the page without your stylesheet. Media queries swap files after the CSS arrives; srcset informs the very first fetch.

What to Read Next

This guide is maintained by the Lucky Graphics editorial team and updated when browser selection behaviour or our own delivery practice changes.

Lucky Graphics Editorial

This guide is maintained by the site editorial team. Sources, limitations, and practical checks are included in the article so readers can verify important details.

Tags
#responsive images#srcset#sizes#image performance#web design#picture element

Found this helpful?

Share this guide with your network

Continue Reading

Ready to Put This Into Practice?

Browse our curated collection of design assets to find the perfect resources for your next project.

Explore Assets