Reference guide · images · Published 2026-08-16 · 3 min read

CSS image-set for optimized background images

CSS image-set function: resolution switching and format fallbacks for background images, with a url() fallback and browser support notes.

CSS background images never get the responsive and format machinery that <img> gets. A background has no srcset and no <picture> sibling, so on an easy setup every device downloads the same single full-size file, and a photo-heavy site with CSS-only heroes and section backdrops carries far more bytes than it needs. The CSS function that restores some of that control is image-set(), which lets the browser pick between candidates by screen resolution and, where supported, by format.

Why backgrounds are hard

An img can declare srcset and sizes so the browser chooses a candidate by viewport and device pixel ratio, and a picture element can switch format with type. A CSS background is just one URL in a background-image declaration with no such negotiation. That is why the common, heavy pattern is a single large background file served to every visitor, including phones that render it far smaller than its natural size. The retina displays article explains the pixel-density problem for images generally, and image-set applies the same idea to a background.

image-set syntax

image-set() accepts a list of URLs, each followed by either a resolution descriptor (1x, 2x) or, for format switching, a type() giving the MIME type:

.hero {
  background-image: image-set(
    url("hero.avif") type("image/avif"),
    url("hero.webp") type("image/webp"),
    url("hero.jpg") type("image/jpeg")
  );
}

.card {
  background-image: image-set(
    url("card.jpg") 1x,
    url("[email protected]") 2x
  );
}

The browser picks the first candidate it can decode, so the format list works as a graceful fallback: AVIF if supported, otherwise WebP, otherwise JPEG. The resolution form mirrors srcset for density: a retina phone selects the 2x file. You can combine both a resolution and a format descriptor on one candidate in the browsers that support the notation.

Fallback and support

Point-for-point support is the one practical catch. The resolution-switching form of image-set() is widely available in current browsers, but format switching with type() is newer and support is uneven, so the safe pattern is to declare a plain background-image: url() first that older browsers ignore the image-set() line and use, and then the image-set() declaration for the browsers that understand it:

.hero {
  background-image: url("hero.jpg");
  background-image: image-set(
    url("hero.avif") type("image/avif"),
    url("hero.jpg") type("image/jpeg")
  );
}

Cascade order matters: the url() fallback must come before the image-set() so a browser that parses only the first line keeps a working background, and the image-set() line overrides it where supported. The next-gen formats article explains why format fallbacks matter, and if you use a background as the hero, the LCP guidance in the background image article notes that a CSS background cannot take the full preload treatment an img can, which is a reason to prefer an img for the LCP element and reserve image-set() for shorter background-heavy sections lower down the page.

Need a website built, fixed, optimised, migrated or replaced?

This technical resource is written by CSMBAC, a small design and development studio. If you would rather hand the problem to a professional, the website service page explains how we build enquiry-ready websites.

Explore website services