Migrate to HD CSS color

This document is part of the high-definition CSS color guide.

Adam Argyle
Adam Argyle

There are two main strategies for updating your web project color to support wide gamut displays:

  1. Graceful degradation: Use the new color spaces and let the browser and operating system figure out which color to show based on display capabilities.

  2. Progressive enhancement: Use @supports and @media to assess the capabilities of the user's browser, and if conditions are met, provide wide gamut colors.

If a browser doesn't understand display-p3 color:

color: red;
color: color(display-p3 1 0 0);

If a browser does understand display-p3 color:

color: red;
color: color(display-p3 1 0 0);

There are advantages and disadvantages to each. Here's a quick list of pros and cons:

Graceful degradation

  • Pros
    • The simplest route.
    • The browser gamut maps or clamps to sRGB if not a wide gamut display, therefore the responsibility is on the browser.
  • Cons
    • The browser may gamut clamp or gamut map to a color you don't love.
    • The browser may not understand the color request and fail entirely. However this can be mitigated by specifying the color twice, letting the cascade fallback to the previous color it does understand.

Progressive enhancement

  • Pros
    • More control with managed color fidelity.
    • An additive strategy that doesn't affect the current colors.
  • Cons
    • You need to manage two separate color syntaxes.
    • You need to manage two separate color gamuts.

Check for gamut and color space support

The browser allows checking for support for wide gamut capabilities and color syntax support from CSS and JavaScript. The exact gamut of colors the user has is not made available, a generalized answer is provided so user privacy is maintained. The exact color space support is made available though, as it's not specific to capabilities of the user's hardware like gamut is.

Color gamut support queries

The following code examples check the visiting user's range of colors in their display.

Check from CSS

The least specific support inquiry is the dynamic-range media query:

Browser Support

  • Chrome: 98.
  • Edge: 98.
  • Firefox: 100.
  • Safari: 13.1.

Source

@media (dynamic-range: high) {
  /* safe to use HD colors */
}

Approximate, or more, support can be inquired with the color-gamut media query:

Browser Support

  • Chrome: 58.
  • Edge: 79.
  • Firefox: 110.
  • Safari: 10.

Source

@media (color-gamut: srgb) {
  /* safe to use srgb colors */
}

@media (color-gamut: p3) {
  /* safe to use p3 colors */
}

@media (color-gamut: rec2020) {
  /* safe to use rec2020 colors */
}

There are an additional two media queries for checking support:

  1. @media (color)
  2. @media (color-index)

Check from JavaScript

For JavaScript, the window.matchMedia() function can be called and passed a media query for evaluation.

Browser Support

  • Chrome: 9.
  • Edge: 12.
  • Firefox: 6.
  • Safari: 5.1.

Source

const hasHighDynamicRange = window
.matchMedia('(dynamic-range: high)')
.matches;

console.log(hasHighDynamicRange); // true || false

const hasP3Color = window
.matchMedia('(color-gamut: p3)')
.matches;

console.log(hasP3Color); // true || false

The above pattern can be copied for the rest of the media queries.

Color space support queries

The following code examples check the visiting user's browser and its selection of color spaces to work with.

Check from CSS

Individual color space support can be inquired using an @supports query:

Browser Support

  • Chrome: 28.
  • Edge: 12.
  • Firefox: 22.
  • Safari: 9.

Source

@supports (background: rgb(0 0 0)) {
  /* rgb color space supported */
}


@supports (background: color(display-p3 0 0 0)) {
  /* display-p3 color space supported */
}


@supports (background: oklch(0 0 0)) {
  /* oklch color space supported */
}

Check from JavaScript

For JavaScript, the CSS.supports() function can be called and passed a property and value pair to see if the browser understands.

CSS.supports('background: rgb(0 0 0)')
CSS.supports('background: color(display-p3 0 0 0)')
CSS.supports('background: oklch(0 0 0)')

Putting the hardware and parsing checks together

While waiting for each browser to implement these new color features, it's a good idea to check for both hardware capability and color parsing capability. This is often what I use when progressively enhancing colors to high definition:

:root {
  --neon-red: rgb(100% 0 0);
  --neon-blue: rgb(0 0 100%);
}

/* is the display HD? */
@media (dynamic-range: high) {

  /* does this browser understand display-p3? */
  @supports (color: color(display-p3 0 0 0)) {

    /* safe to use display-p3 colors */
    --neon-red: color(display-p3 1 0 0);
    --neon-blue: color(display-p3 0 0 1);
  }
}

Debug color with Chrome DevTools

Chrome DevTools is updated and equipped with new tools to help developers create, convert and debug HD color.

Updated color picker

The color picker now supports all the new color spaces. Allowing authors to interact with channel values just as they would have.

DevTools showing display-p3 color support.

Gamut boundaries

A gamut boundary line has also been added, drawing a line between srgb and display-p3 gamuts. Making it clear which gamut the selected color is within.

DevTools showing a gamut line in the color picker.

This helps authors visually differentiate between HD colors and non-HD colors. It's especially helpful when working with the color() function and the new color spaces because they're capable of producing both non-HD and HD colors. If you want to check which gamut your color is in, pop up the color picker and see!

Convert colors

DevTools has been able to convert colors between supported formats like hsl, hwb, rgb and hex for many years. shift + click on a square color swatch in the Styles pane to perform this conversion. The new color tools don't just cycle through conversions, they yield a dialog where authors can see and pick the conversion they want.

When converting, it's important to know if the conversion was clipped to fit the space. DevTools now have a warning icon to the converted color that alerts you to this clipping.

Screenshot of DevTools gamut clipping, with a warning icon next to the color.

Discover more CSS debugging feature in DevTools.

Next steps

More vibrance, consistent manipulations and interpolations and overall deliver a more colorful experience to your users.

Read more color resources from the guide.