CSS image-set() for Responsive Raster Graphics

The CSS image-set() function provides a native way to deliver responsive raster graphics via CSS properties such as background-image. Much like the HTML srcset attribute on the <img> element, image-set() allows developers to supply a list of image sources paired with resolution and format conditions, enabling the browser to automatically select and download the optimal asset based on a user's display capabilities and network conditions. This article explains how image-set() works, how it manages device pixel density and modern image formats, and how to implement it cleanly.

Resolution Switching for High-DPI Displays

Serving high-resolution (Retina/high-DPI) background images historically required complex media queries relying on min-resolution or vendor-prefixed device pixel ratios. The image-set() function streamlines this by accepting resolution descriptors such as 1x, 2x, or specific dpi values directly inside the property declaration.

.hero-banner {
  background-image: image-set(
    url("hero-standard.jpg") 1x,
    url("hero-retina.jpg") 2x
  );
}

When evaluating this rule, a standard display (1x) downloads the smaller file, saving bandwidth and reducing load times. A high-density screen (2x or higher) downloads the sharper asset to prevent visual blurring. The browser handles this decision internally, eliminating the need for duplicated CSS rules and media query blocks.

Format Negotiation with type()

Modern specifications of image-set() allow format-based content negotiation using the type() function. This enables developers to serve modern raster formats like AVIF and WebP without relying on JavaScript or server-side user-agent sniffing.

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

The browser evaluates the sources from top to bottom and downloads the first format it supports. Format detection can also be combined with resolution descriptors to deliver the most efficient file for any given scenario:

.avatar {
  background-image: image-set(
    url("avatar-2x.avif") type("image/avif") 2x,
    url("avatar-1x.avif") type("image/avif") 1x,
    url("avatar-2x.jpg") type("image/jpeg") 2x,
    url("avatar-1x.jpg") type("image/jpeg") 1x
  );
}

Fallbacks and Compatibility

Modern browsers fully support the standardized image-set() syntax. However, to guarantee compatibility with older legacy browsers that do not recognize the function, always supply a standard background-image fallback declaration before the image-set() property:

.thumbnail {
  background-image: url("fallback.jpg");
  background-image: image-set(
    url("optimized.webp") type("image/webp") 1x,
    url("optimized@2x.webp") type("image/webp") 2x,
    url("fallback.jpg") type("image/jpeg") 1x,
    url("fallback@2x.jpg") type("image/jpeg") 2x
  );
}

By decoupling image resolution selection from layout logic, image-set() keeps stylesheets concise, conserves user data, and ensures raster graphics remain crisp across various screen densities and browser environments.