Serving AVIF Images to P3 Displays with CSS color-gamut

Modern web standards allow developers to deliver tailored visual assets based on the exact hardware capabilities of a user's device. By pairing the AVIF image format with the CSS color-gamut media feature, websites can dynamically serve wide-gamut, high-fidelity P3 imagery exclusively to screens capable of rendering those colors. This targeted delivery ensures users with advanced displays experience richer visuals without burdening standard displays with heavier, wide-color assets they cannot physically show.

Understanding Display P3 and color-gamut

Most traditional computer monitors are limited to the sRGB color space. However, many modern smartphones, tablets, and laptops now feature Display P3 screens, which offer roughly 25% more color volume than sRGB—particularly visible in vivid greens, reds, and deep secondary shades.

The CSS color-gamut media feature queries the output device to determine the approximate range of colors supported by the browser and display hardware. It accepts three primary values: srgb, p3, and rec2020. When a query checks for (color-gamut: p3), it evaluates to true only if the user's hardware can render at least the Display P3 color gamut.

Why AVIF Fits the P3 Profile

While formats like JPEG and WebP can technically embed wide-gamut color profiles, they are often constrained to 8-bit color depth, which risks noticeable color banding when stretching gradients across a wider spectrum. AVIF natively supports 10-bit and 12-bit color depths, high dynamic range (HDR), and wide color gamuts (WCG) with superior compression efficiency. This makes AVIF the ideal format for wide-gamut encoding.

Conditional Delivery via HTML Picture Element

The primary method to serve AVIF exclusively to P3 displays within content is by using the HTML <picture> element. The media attribute on the <source> tag accepts standard CSS media queries, enabling a combined check for format support and screen capabilities:

<picture>
  <!-- Serves wide-gamut AVIF only to displays supporting P3 -->
  <source 
    srcset="photo-p3.avif" 
    type="image/avif" 
    media="(color-gamut: p3)">
  
  <!-- Serves standard sRGB AVIF to non-P3 displays that support AVIF -->
  <source 
    srcset="photo-srgb.avif" 
    type="image/avif">
  
  <!-- Standard fallback for browsers without AVIF support -->
  <img 
    src="photo-srgb.jpg" 
    alt="Descriptive image text" 
    loading="lazy">
</picture>

In this setup, the browser evaluates the sources sequentially. If the browser supports AVIF and the monitor supports the P3 gamut, it downloads photo-p3.avif. If the screen only supports standard sRGB, it skips the first source and downloads the sRGB-optimized asset instead.

Conditional Delivery in CSS

For UI elements and background images defined in stylesheets, the @media rule handles this logic directly:

.hero-banner {
  background-image: url('hero-srgb.webp');
}

@media (color-gamut: p3) {
  @supports (background-image: url('test.avif')) {
    .hero-banner {
      background-image: url('hero-p3.avif');
    }
  }
}

Using this approach, standard displays receive a compressed sRGB asset, while P3-capable displays load the wider-gamut AVIF image, unlocking deeper color saturation where supported while maintaining strict performance parity across devices.