@media (color-gamut): progressive enhancement for vivid screens
Detect the screen, not the browser
Not every "modern" browser is on a wide-gamut screen. Your visitor might use a 2018 budget laptop. So your fallback shouldn't be "always serve P3" β it should be "serve sRGB by default, opt into P3 when the display can show it."
.brand { color: oklch(0.55 0.25 27); } /* sRGB-safe default */
@media (color-gamut: p3) {
.brand { color: color(display-p3 0.95 0.20 0.18); }
}
@media (color-gamut: rec2020) {
.brand { color: color(rec2020 0.95 0.20 0.18); }
}color-gamut reports what range the display supports, regardless of OS or browser. Values from narrowest to widest:
| Value | Coverage |
srgb | the 1996 baseline |
p3 | display-p3, ~25% wider than sRGB |
rec2020 | the HDR-cinema gamut, ~75% wider than sRGB |
The browser picks the most specific block where the screen meets the requirement.
What this gives you
Designers can publish two color tokens β sRGB-safe and wide-gamut β and the user automatically sees the right one without you sniffing for it.
What to remember
- Pair this with OKLCH everywhere. OKLCH compresses gracefully when out of gamut, so even the sRGB fallback looks intentional.
- Don't gate critical contrast on
color-gamutβ the sRGB version must still pass WCAG. Wide-gamut is a "looks even nicer" upgrade, not a "now legible" one.
Sign up to start coding
Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial β card required, cancel anytime.
Sign up β free trial βFirst 10 lessons in each track are free. No card needed for those.