CSS image-set Table

PieceWhat it doesField note
image-set(url 1x, url 2x)srcset for CSSResponsive images inside CSS - backgrounds, masks, content
Resolution descriptors1x / 2x / 600dpiBrowser picks by DPR - same negotiation as img srcset
type: optionFormat hintsimage-set(avif 1x type("image/avif"), png 1x) - format AND size switch
gradient in image-setAny image valueGradients and SVGs are valid options - fallback to solid
vs img srcsetCSS vs HTML contextsrcset for CONTENT images; image-set for CSS-declared images
Fallback declared firstThe cascade safetybackground: url(fallback); background: image-set(...) - old engines keep first
Performance winNo double downloadBrowser picks ONE file - unlike media-query stacking which fetches wrong guesses
Baseline 2023Safe to shipAll evergreen browsers - the years of -webkit-image-set are over
Reference: the MDN image-set reference. image-set() is srcset for CSS: image-set(url(hero-2x.png) 2x, url(hero.png) 1x) lets the BROWSER pick the right file by device pixel ratio - inside backgrounds, masks and content. The type() option adds format switching (AVIF with PNG fallback) in the same declaration - format AND resolution negotiation together. Bottom line: declare the plain fallback first (background: url(...) then the image-set line), old engines keep the first, evergreen browsers (baseline 2023) pick one file - no double downloads like media-query stacking. Related tools: img table (the HTML-side srcset contract), backgrounds table (where image-set slots in), and mask table (the other image-taking property).

image-set() is srcset for CSS: image-set(url(hero-2x.png) 2x, url(hero.png) 1x) lets the BROWSER pick the right file by device pixel ratio - inside backgrounds, masks and content, the places HTML srcset cannot reach.

Bottom line: the type() option adds format switching (AVIF with PNG fallback) in the same declaration - format AND resolution negotiation together. The cascade pattern ships safety: declare the plain fallback background first, then the image-set line - old engines keep the first, evergreen browsers pick one file.

The honest part: baseline 2023 - the years of -webkit-image-set are over. The performance property that justifies it: the browser picks ONE file, unlike media-query stacking where wrong guesses prefetch images the layout never shows.

How to use

  1. Serve sharp backgrounds: background: image-set(url(bg-2x.jpg) 2x, url(bg.jpg) 1x) - every display gets its resolution, one declaration.
  2. Negotiate format too: image-set(avif-hero.avif 1x type('image/avif'), hero.png 1x) - AVIF where supported, PNG where not, same resolution logic.
  3. Ship the fallback first: background: url(bg.jpg); background: image-set(...); - the cascade keeps old engines on the plain URL, new engines on the set.

Frequently asked questions

What does image-set() solve that plain CSS background images could not?

Device-pixel-ratio awareness. A plain background: url(bg.png) ships one file to every screen: blurry on retina (1x file stretched over 4 physical pixels) or wasteful everywhere else (2x file downloaded for 1x screens). image-set() lists resolution options with descriptors (url 1x, url 2x) and the browser downloads exactly the file matching the device - the same negotiation img srcset performs, brought to every CSS image context: backgrounds, masks, border images, the content property. Before it was widely supported, the workaround was media queries stacking -webkit-device-pixel-ratio conditions - verbose, and it fetched wrong guesses.

How does the type() option extend the negotiation?

It adds FORMAT to the resolution axis. Each option can carry type('image/avif'), and the browser skips options whose format it cannot decode - so one declaration offers AVIF (smallest), WebP (middle), and PNG (universal): format negotiation and DPR negotiation in one function. The same idea exists in HTML as <source type> inside picture; image-set brings it to CSS contexts. The practical check is the same as srcset: the type strings must be valid MIME types, and the browser trusts them - a wrong type string excludes a file the browser could actually have used.

Why declare a plain fallback background BEFORE the image-set line?

Cascade safety for old engines. A browser that does not parse image-set() discards the entire declaration - if the image-set line is the only background, the element has NO background at all. Declaring background: url(bg.jpg) on the previous line means unsupported engines keep the plain file (cascade: later valid declaration wins, later INVALID declaration is ignored), while supporting engines override it with the image-set choice. It is the same fallback-first discipline as modern CSS features generally: the enhancement line comes second, the functional baseline comes first.

When is image-set the wrong tool compared to img srcset?

For CONTENT images. An image that is the content - a product photo, an article illustration - belongs in an <img> with srcset and sizes: it gets alt text, semantic loading semantics, lazy loading, and the browser's priority hints. image-set is for images that are DECORATION or style: backgrounds, masks, list bullets, pre-play posters on video. The dividing question: would this image appear in an RSS reader or matter to a screen reader? If yes, it is content - img. If it is presentation the page works without, CSS owns it, and image-set is how CSS images go responsive.

Related tools