Skip to content

Gamut mapping #1394

Open
Open

Description

@LeaVerou

Description

CSS currently provides several ways to define and manipulate colors, that are independent of any particular RGB gamut, such as oklch() or lab().

While this makes it easier to define and manipulate colors in ways that are closer to human perception, it also makes it much easier to define colors that fall outside of the display gamut of any output device, especially when modifying existing colors (that are in gamut to begin with!), such as when creating color ramps from a dynamic accent color.

For example, pick any non-neutral accent color (e.g. #0075ff, Chrome’s default AccentColor value), and adjust its OKLCh lightness to 97% to produce a tinted background color. The result (oklch(from #0075ff 97% c h) or oklch(0.97 0.2235 258.41)) is outside the display gamut of any conceivable display device. Without gamut mapping (i.e. currently in most UAs), this is displayed via converting to RGB, and clipping red, green, blue coordinates. This produces colors dramatically different than the specified color, losing all guarantees that these color spaces were supposed to provide.

This carries accessibility implications as well, since RGB clipping can significantly affect contrast characteristics, making color pairs inaccessible. See here a particularly egregious example where white is displayed as blue in non-GM browsers (bsky post).

To display these colors correctly they need to be mapped to the closest in-gamut color, typically by reducing chroma (≈ saturation) while preserving hue and lightness. Here is a visual of the example above, with each color as a dot shown relative to the P3 gamut:

#0075ff oklch(from #0075ff 97% c h) oklch(from #0075ff 97% c h), gamut mapped to P3
Color Image Image Image
Color relative to P3 gamut Image Image Image

Notice how the gamut shrinks dramatically as we get towards white (100%) or black (0%), so a color that was perfectly in-gamut for midtones, can be wildly out of gamut for lighter tints. We promised authors that color spaces like oklch() + relative colors would let them create dynamic color ramps, but that promise was never realized due to the lack of GM.

CSS Color 4 defines three gamut mapping algorithms that browsers can pick from (comparison), but so far only Firefox has shipped an implementation. Soon, it may be too late to fix this due to web compat.

This was previously submitted in 2024 by @romainmenke in #443 and rejected on the basis of lacking testing infrastructure. There are currently more tests than there were back then. Canvas makes it easier to test at least for specific colorSpace values.

In terms of implementations, Firefox has implemented GM behind a flag and Chrome and WebKit are reportedly looking into it.

Specification

https://www.w3.org/TR/css-color-4/#css-gamut-mapping

web-feature

gamut-mapping

Test Links

https://wpt.fyi/results/css/css-color/lch-009.html
https://wpt.fyi/results/css/css-color/lch-010.html
https://wpt.fyi/results/css/css-color/lch-l-over-100-1.html
https://wpt.fyi/results/css/css-color/lch-l-over-100-2.html
https://wpt.fyi/results/css/css-color/oklch-009.html
https://wpt.fyi/results/css/css-color/oklch-010.html

Additional Signals

At CSS Day, gamut mapping was the top requested feature:

Image

In State of CSS, color pain points revolve around creating color ramps, or how confusing oklch is, both issues that are largely or completely solved by GM (the site is broken right now, so I can't cite specific things, this is from memory).

Activity

  1. github-actions commented on Sep 14, 2026

    @github-actions

    This comment was automatically generated based on the information you provided. Please don't edit it.

    Below is additional information about the web feature (from the web-features project) which is referenced in your proposal.
    If this doesn't accurately correspond to your proposal, please update your initial comment to include web-features: <feature-id>.
    To find feature IDs, use the web-features explorer.

    Feature Gamut mapping

    • ID: gamut-mapping
    • Name: Gamut mapping
    • Description: Colors in CSS and <canvas> elements can be defined out of range of an output device or the color space of the canvas. Gamut mapping brings the color into range while preserving hue and lightness.
    • Baseline status: Limited Availability
    • Developer signals: 6 votes / 2 use cases (details)
    • More information: See the web-features explorer
  2. spartanatreyu commented on Sep 16, 2026

    @spartanatreyu
  3. svgeesus commented on Sep 26, 2026

    @svgeesus

    @LeaVerou please add these two tests to your original post:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions