Color in CSS showed that oklch() can name colors no screen can show, and that @supports says nothing about the screen at all. This page picks up the color after the style sheet is done with it: the screen it is drawn on, the light in the room, and the paper it may end up on. Two demos let you see both halves. The first asks your screen what it can show; the second puts one small interface through five conditions it will meet in real use.
1. After the style sheet
A color in a style sheet is a request. The browser parses it, computes it, and converts it into the color space of the screen. If the screen cannot show it, the browser replaces it with one it can. Then the color leaves the browser's hands. The panel draws it at the brightness the reader set, warmed or cooled by the operating system; light from the room adds to it; and the reader's eyes, which differ from person to person and change with age, do the rest.
The split in the diagram is the plan for the page. For the steps inside the browser, a page can ask questions and get answers: what gamut the screen covers, whether it can show high dynamic range, whether the output is paper. For the steps outside, it gets no answers. No media feature reports glare, a projector, a night-shift setting or a grayscale filter. Those are handled the way an engineer handles loads that cannot be measured in advance: with margin.
That gives this page its rule of thumb. Enhance for the best screen; design for the worst conditions. A vivid P3 green on a new phone is a pleasure, and costs little to offer. But the token has to work first on a dim office monitor, a projector at the front of a lit lecture hall and a phone at a bus stop, because more readers are in those conditions than in front of a calibrated studio display.
2. The gamut ladder
How color works drew the three gamuts that matter on the web as nested triangles on a chromaticity diagram. Read as a ladder, from smallest to largest:
- sRGB, proposed in November 1996 and the web's default since CSS1, a month later. Every hex value, every named color and everything written with
rgb(),hsl()orhwb()lives here. Untagged images are treated as sRGB too, as section 6 explains. - Display P3, which keeps sRGB's blue, reaches further toward red and much further toward green. Apple shipped it widely first: the WebKit blog's 2020 introduction, "Wide Gamut Color in CSS with Display-P3", lists the iMac from 2015, the MacBook Pro and iPad Pro from 2016, and the iPhone 7 and later. Most current phones, many laptops and a growing share of monitors cover all or nearly all of it.
- Rec. 2020, the color standard for ultra-high-definition television, with primaries close to the edge of human vision. Current screens cover only part of it. It is a target for the future more than a gamut anyone designs for today.
Triangles on a chromaticity diagram hide something useful: how much each rung adds depends on the hue. The chart below asks a more practical question. At one lightness, 70% in OKLCH, how far can chroma go in each hue before the color leaves each gamut?
Three lessons sit in those bars. First, P3's gain is uneven: about a third more chroma for green and cyan, a quarter more for red, and almost nothing for yellow and blue. A wide-gamut screen makes foliage, flags, sale badges and teal water look different; it barely changes a blue link. Second, the maximum depends on lightness as well as hue, so no single chroma number is "safe" for a whole palette. Third, Rec. 2020 adds a great deal of cyan that today's panels cannot yet show, which is why the useful step on the web today is the first one, from sRGB to P3.
A design limited to sRGB is not wrong. It is the safe default, and every color in this section's demos that has to match across screens sits inside it. But it does leave the most vivid greens, reds and cyans of a modern screen unused, and the next three sections show how to offer them to the screens that can show them without breaking the screens that cannot.
3. Asking the screen: color-gamut and dynamic-range
Two media features describe the screen rather than the browser or the reader. color-gamut is defined in Media Queries Level 4 and carried into Level 5; dynamic-range is new in Level 5 (Working Draft, 19 February 2026). Both are Baseline widely available.
color-gamuttakessrgb,p3orrec2020, and each value means "approximately this gamut or more". So the values nest: a P3 screen matches both(color-gamut: srgb)and(color-gamut: p3). It became Baseline in February 2023, when Firefox 110 shipped it, and widely available in August 2025 (Chrome 58, Safari 10).dynamic-rangetakesstandardorhigh.highmeans the screen and the browser together can show high peak brightness, a high contrast ratio and more than eight bits per channel. The specification notes that it tests what the device is capable of, not whether an HDR mode happens to be on. Baseline since May 2022, widely available since November 2024 (Chrome 98, Firefox 100, Safari 13.1).
Scripts ask the same questions with matchMedia(). The answer is a MediaQueryList, whose matches property gives the answer now and whose change event gives it later. That second part matters more than it looks. Media features describe the output device, and the output device can change while the page is open: drag a window from a laptop's P3 screen to an older external monitor and the right answer changes with it.
As Color in CSS showed, these are different questions from @supports. CSS.supports("color", "color(display-p3 1 0 0)") is true in every current browser, on every screen, because it asks whether the browser can parse the notation. matchMedia("(color-gamut: p3)") asks whether the screen can show the color. A page that wants to know what the reader will actually see needs the second question.
One browser always answers sRGB
The two answers can still mislead. MDN's compatibility data notes that in Firefox, on the desktop and on Android, color-gamut: p3 is always false and color-gamut: srgb always true, "because Firefox does not support wide-gamut color". Firefox parses oklch() and color(display-p3 …), but as of October 2026 it draws CSS colors in sRGB even on a P3 screen; Mozilla's bug 1626624, "Support Wide Gamut Color in CSS with Display-P3", is still open. That is not a bug in the media feature. Firefox reports truthfully what it can show, and that is the right reading of the feature: the combination of browser and screen, not the screen alone.
Measuring the share of wide-gamut readers
A team deciding whether wide-gamut color is worth the effort can measure. A field script can count how many visits match (color-gamut: p3) and (dynamic-range: high). Each of those answers is also one more bit that helps tell one visitor's device from another, so collect counts, not per-visitor profiles; Privacy explains why. The same applies to every preference query in this section.
4. Wide gamut, progressively
Offering vivid color to P3 screens is a progressive enhancement, and there are two ways to write it. Both rely only on features that every current browser has.
Strategy 1: write the vivid color and let the browser map it
The shortest version is a single oklch() value with more chroma than sRGB allows. A P3 screen shows it as written. An sRGB screen cannot, so the browser maps it to a color it can show. No media query is needed:
It is simple, and for decoration it is often enough: a photo caption's accent, an illustration, a gradient that is meant to glow. The cost is control. What the sRGB reader sees is decided by the browser's mapping, which, as the next section shows, is not what the specification describes and may differ between browsers. And a contrast ratio computed from the token is not the one an sRGB reader gets.
Strategy 2: an sRGB token first, a P3 token where the screen can show it
The explicit version writes two values. The first sits inside sRGB and is the color every reader gets. The second replaces it only where color-gamut says the screen can show more:
It is more code, and it asks someone to choose the second color on purpose. In return, every reader gets a color that was chosen for their screen rather than computed by a mapping, and both colors can be checked. Here the dark label measures 7.3:1 on the sRGB green and 7.5:1 on the P3 one. Keeping the lightness and hue of the two tokens the same and changing only the chroma, as here, keeps their contrast close, which is one more reason to write tokens in oklch().
Note what neither strategy needs: an @supports test for oklch() itself. Every current browser parses it, and a token inside sRGB written in oklch() is drawn the same by all of them. For readers on browsers from before 2023, the fallback-first habit of Color in CSS still applies.
Which to use
- For anything that must match or must be legible, such as brand colors, text, buttons, status colors and anything with a contrast requirement: strategy 2, or simply stay inside sRGB.
- For decoration, such as illustrations, gradients and accents with no text on them: strategy 1 is reasonable, as long as the color still works when it is mapped down.
- For images, the image file carries its own color space, and the browser handles it without any CSS; see section 6.
5. When the screen falls short
Every color outside the screen's gamut has to be replaced by one inside it before it can be drawn. Color in CSS described what the specification asks for: CSS Color 4 (Candidate Recommendation Draft, 27 October 2026) defines CSS gamut mapping as reducing chroma in OKLCH, keeping lightness and hue, until the color fits, and calls clipping each channel "the least acceptable method". Then it measured Chrome clipping. That measurement is worth repeating more widely, because it changes the advice.
What browsers do, measured
For this page, the same colors were drawn on an sRGB surface in two engines and the pixels read back, in October 2026: Chrome 156, and WebKit 26.6 in the build that the Playwright testing tool ships, which is the engine inside Safari but not Safari itself. Both drew exactly the same pixels, and the pixels were what per-channel clipping predicts. Firefox could not be measured the same way; since it draws CSS colors in sRGB, it has to map every wide-gamut color too.
| Requested | Drawn (clipped) | CSS Color 4 chroma reduction |
|---|---|---|
oklch(90% 0.3 250), a pale, intense sky blue | #00dfff, about oklch(83% 0.145 213): darker and turned toward cyan | #bae3ff, about oklch(89.6% 0.058 238): the same lightness, much paler |
oklch(70% 0.3 145), a vivid green | #00c800, about oklch(72.2% 0.246 142) | #00c300, about oklch(70.8% 0.241 142) |
oklch(70% 0.25 145), just outside sRGB | #00c30b | #00c30b: identical |
color(display-p3 1 0 0), P3's reddest red | #ff0000, about oklch(62.8% 0.258 29) | #ff0b0c, about oklch(63% 0.255 29): almost the same |
The right-hand column was computed for this page with the specification's binary-search algorithm, so it shows what a browser following CSS Color 4 would draw; no browser measured here does. That search stops as soon as clipping the current candidate would change it by less than a just-noticeable difference (a distance of 0.02 in Oklab, written ΔEOK), and returns the clipped color, so a result with little chroma left can drift in hue: the pale blue ends at hue 238, not 250. Two patterns stand out.
Far outside the gamut, the methods disagree. The pale, intense blue in the table's first row is the worst case, and the one Color in CSS measured: clipping turns it into a darker cyan, while chroma reduction keeps it light and blue and gives up most of its color. Neither is the color the token describes, and the two are not even close to each other. A designer who chose that blue on a P3 screen and checked it on nothing else would be surprised by both.
Near the edge, they agree. The green just outside sRGB comes out the same either way, because a small step inward lands in the same place. That is the practical consequence, and it does not depend on which browser follows the specification first.
The practical rule: moderate chroma for colors that must match
- Keep any color that must match inside sRGB, or close enough to its edge that mapping barely moves it. Brand colors, text, buttons, status colors and focus rings are in this group. A color inside sRGB is drawn the same by every browser on every screen, and its contrast ratio can be computed once and trusted.
- Treat high chroma as a P3 enhancement, declared in
@media (color-gamut: p3)with an sRGB token before it, so no reader gets a mapped color that nobody chose. - Check contrast on what is drawn, not only on what is written. Clipping changes lightness, so it can raise or lower the contrast of a label on a clipped background: the gamut swatch's red loses half a point, from 6.1:1 to 5.6:1, while its green and cyan gain a little. A pair that only just passes on paper can fail on screen.
- Check light tints with extra care. The limit of sRGB closes in fast at high lightness: at 90% lightness, red and blue cannot pass a chroma of about 0.05 in sRGB, while yellow and green still allow nearly 0.2. A "light but vivid" tint is the most likely kind of token to fall outside the gamut by accident.
oklch.com draws the sRGB and P3 boundaries as you move its sliders, which makes the last point easy to see. The Chrome team's High definition CSS color guide covers every new space with interactive examples.
6. Images carry their own color
Images do not go through any of the CSS above. An image file can say which color space its pixels are in, and the browser converts them to the screen's space itself. CSS Color 4 describes the two cases:
- A tagged image names its color space, usually with an embedded ICC profile, a description of the space in the format of the International Color Consortium. JPEG and PNG can embed one, and so can WebP and AVIF. Some formats have shorter tags: PNG's
sRGBchunk says "this is sRGB" without a full profile, and itscICPchunk can name Display P3 or an HDR space. The browser must honor a valid tag: a Rec. 2020 image shown on a P3 screen must be converted, not read as if its numbers were P3. - An untagged image has no tag, or an invalid one, and "must be treated as being in the sRGB color space". The same rule covers colors given in HTML attributes. Untagged video is the exception; it is assumed to be in the television standard that suits its size.
So a photograph taken on a P3 phone and saved with a Display P3 profile shows its full gamut on a P3 screen, in every browser that color-manages images, with no CSS at all. Three habits follow:
- Keep the profile, or convert before you drop it. Some optimizers remove metadata to save bytes, and an ICC profile is metadata;
jpegtran -copy none, for example, drops it without converting the pixels. Removing a P3 profile without converting the pixels leaves P3 numbers that the browser will read as sRGB, and the photo goes dull and slightly off in hue. A careful pipeline either keeps the profile or converts the pixels to sRGB first, then strips it. - Do not expect a CSS color to match a photo by its numbers. A brand orange sampled from a P3 photo with an eyedropper and typed as hex is an sRGB color; on a P3 screen it can look duller than the same orange in the photo next to it. Sample in the right space, or choose the token by eye on the target screens.
- Text in images does not adapt. It cannot follow dark mode, forced colors or a reader's contrast settings, which is one reason Type for people argues against images of text.
Images: formats covers the formats themselves; its WebP and AVIF section describes the newer formats that carry wide-gamut and HDR images most efficiently.
7. HDR, as a preview
High dynamic range is a separate dimension from gamut. Gamut is how colorful a screen can be; dynamic range is how far it can go from its darkest black to its brightest highlight. An HDR screen can show highlights brighter than the white of a page, the glint of sun on water in a photo, while still showing deep blacks. On the web today that ability is used mostly by images and video. For CSS colors, white is still the brightest a page's text and backgrounds get.
Detecting it
@media (dynamic-range: high), from section 3, is the one widely available piece. Media Queries 5 also defines video-dynamic-range, for devices whose video plane can do more than the rest of the screen, as on some televisions; MDN's data shows it only in Firefox, from version 100, behind a flag in Chrome and absent in Safari, so it is not yet a feature to rely on.
dynamic-range-limit
HDR content beside ordinary content can be jarring: a thumbnail grid in which one HDR photo glows far brighter than the page around it, or than the photos beside it. The dynamic-range-limit property lets a page cap how bright an element's HDR content may go:
standard: no brighter than the page's white, the "HDR reference white".constrained: somewhat brighter than that white, so HDR and ordinary content sit comfortably together. The exact level is left to the browser.no-limit: as bright as the content asks for. This is the initial value, and the property is inherited.dynamic-range-limit-mix(): a blend of the keywords by percentage, which also lets the limit be animated.
Support is limited, and the sources disagree on how limited. MDN's data, updated October 2026, records Chrome and Edge 136 with all four values, and Safari 26 with standard and no-limit only. webstatus.dev lists only the Chromium browsers. Firefox has none. Either way it is an enhancement: a browser without it shows HDR images at their full brightness, which is the situation before the property existed.
The order of the two tests says what each one asks: the media query asks about the screen, @supports about the browser. Without either, the images are simply shown as they are. Note that a brightness change on hover is a change only some readers will see; it must never carry information.
The CSS Color HDR draft
The property comes from the CSS Color HDR Module Level 1, a Working Draft whose first public version appeared on 17 December 2024 and whose latest is dated 26 October 2026. It goes further than images. It anchors the page's white at 203 candelas per square meter, the HDR reference white; it adds color() spaces for HDR video standards (rec2100-pq, rec2100-hlg and rec2100-linear) and HDR color functions such as jzazbz() and ictcp(); and it proposes hdr-color(), a color that blends between two values according to how much brighter than white the screen can currently go. Treat all of that as a preview. A draft can change before browsers ship it, and an HDR highlight used for text or interface parts would raise new questions about contrast and comfort that WCAG does not yet answer.
8. The screen itself
Before any light from the room reaches it, the panel has already changed the color. Two screens showing the same token side by side rarely agree, for reasons no media feature reports.
- Brightness. Readers set it, phones change it with the light around them, and battery savers lower it. Contrast ratios do not change with brightness, but the eye separates dark shades poorly in dim light, so on a dimmed screen the darkest colors run together. Near-black surfaces in a dark palette suffer first.
- Calibration. Almost no reader's screen is calibrated. Panels differ from model to model and from unit to unit, TVs and some monitors ship in a "vivid" mode that pushes saturation, and some lack a color profile, so the system cannot correct them. The designer's screen is one sample, not the reference.
- Gamma, then and now. The transfer curve that How color works describes has to match between a file and the screen. For years it did not: until Mac OS X 10.6 in 2009, Macs used a display gamma of 1.8 and Windows used 2.2, so an image or a page color designed on a Mac looked darker and heavier on a PC. Since 10.6 both use 2.2, close to sRGB's own curve, but a monitor's gamma setting and an uncalibrated panel can still make the midtones lighter or darker than intended.
- Age. Screens drift. Backlights and the phosphors of old tubes dim over the years; OLED subpixels wear unevenly, blue usually fastest, which shifts the white point and can leave a burned-in shadow of a static interface. An office monitor several years old is dimmer and warmer than it was new.
- Viewing angle. Inexpensive TN panels lose contrast, and can shift or even invert colors, when seen from above, below or the side; IPS and OLED panels hold up better. The person beside the presenter at a meeting table sees a different page.
The page sees none of this. As with the room, the defense is margin: contrast above the minimum, lightness that differs as well as hue, and a palette that was checked on more than one screen, ideally including an old one.
9. The room
The panel is the last step inside the device. Then the room adds its own light. Why color matters introduced the problem; here are the conditions one at a time, with what each does to a palette.
- Sunlight and glare. Light reflected off the screen's surface adds to both the text and the background. Both get lighter by the same amount, so the ratio between them shrinks. Dark text on a light background survives best; pale grays, light tints and thin text go first.
- Projectors. A projector's black is only as dark as the screen in a lit room, so the darkest colors lift toward gray, and its white is dimmer than a laptop's. Most projectors also show less saturated color than the laptop feeding them, and some shift hues. Two greens that were clearly different on the laptop can become one green on the wall, and a pale divider disappears.
- Night shift and warm white points. Night Shift on Apple devices, Night Light on Windows and Android, and similar settings warm the screen in the evening by turning down blue, and True Tone on Apple devices adjusts the white point to match the room's light. Whites become cream and blues lean toward purple or gray. Contrast changes little; hue changes a lot, so a palette that tells states apart by blue against purple, or relies on a cool white for "clean", loses that distinction.
- Grayscale. Phones and desktops offer grayscale as an accessibility setting and as a "bedtime" or focus mode, and e-ink readers show gray by nature. Hue disappears entirely. Contrast based on luminance survives, so a palette whose states differ only in hue becomes a set of identical grays.
- Battery savers. Some battery-saving modes switch the system to its dark theme, which a page following
prefers-color-schemewill pick up; Light and dark covers that. Others dim the screen, which makes every margin smaller.
A page cannot sense the room
It would be convenient to ask. Media Queries once had a light-level feature, with the values dim, normal and washed, drafted for Level 4 and carried into the first drafts of Level 5. No browser shipped it, and in 2020 the editors removed it from Level 5 "as it is redundant with prefers-contrast and prefers-color-scheme". The specification now suggests the platform do the sensing instead: a device with an ambient light sensor "could automatically switch prefers-contrast to more" when the screen is hard to read in bright light, or switch to less contrast and a dark scheme in a dim room. So the best a page can do is respect those two preferences, and let the device decide when to set them.
Night shift and grayscale filters are invisible too. The operating system applies them after the browser has drawn the page, so the page sees its own colors, and no media feature changes. The only defense is a palette that does not need hue to work and has contrast to spare.
Design margin
WCAG's 4.5:1 for body text is a minimum for good conditions, not a target. The one-card demo on page 01 showed a sold-out size that passed at 4.7:1 indoors and fell to about 2.7:1 under a rough sunlight filter. The demo below does the same for five conditions at once.
Three habits come out of it:
- Aim well above the minimum for anything important. In the demo, body text near 15:1 survives both the projector and the sun; even the 7.5:1 link falls below 4.5:1 under both. Save the narrow margins for decoration, and give the pairs that matter all the margin the design allows.
- Make lightness do the work. If two states differ in lightness as well as hue, they survive grayscale, color vision differences and warm white points. Equal-lightness palettes are a strength for harmony and a weakness for telling states apart; give states a second cue as well.
- Test in the real room. Run the fixed Trail report and the discolored one side by side on the classroom projector, then look at a phone in the sun. Chrome's DevTools can help before that: its Rendering panel emulates
color-gamut, print media,prefers-contrastand forced colors, and simulates several kinds of color vision deficiency, including achromatopsia, which shows the page in grayscale.
10. Monochrome
One kind of grayscale output does announce itself. The monochrome media feature gives the number of bits per pixel of a monochrome display, and 0 for a color one, so @media (monochrome) matches any monochrome device. It is one of the oldest media features: MDN's data records it in Chrome 1, Firefox 2 and Safari 3. It is meant for e-ink readers and black-and-white printers, and the specification's own example pairs it with print: one style sheet for print and (color), another for print and (monochrome).
Treat it as a hint, not a guarantee. Whether a particular e-reader's browser reports monochrome is up to that browser, and the grayscale settings of phones and desktops do not set it in current browsers, because the browser still draws in color and the system removes the color afterward. A page that works in grayscale without the media query, because every state has a word, an icon, a shape or a pattern as well as a color, does not need to know.
11. Print
Responsive design introduced the print style sheet: hide what paper cannot use, control page breaks, expose links. Color adds two concerns of its own.
Browsers drop backgrounds to save ink
By default, browsers do not print background colors or background images. The rule is print-color-adjust, from CSS Color Adjustment Level 1 (a Candidate Recommendation Snapshot, 16 December 2025), and its initial value is economy: the browser "should make adjustments to the page's styling as it deems necessary and prudent for the output device", and the specification's example is to drop backgrounds and darken text to save ink. A reader can override it in the print dialog, with an option such as Chrome's "Background graphics", but few do.
Usually that is right. A dark theme printed as a sheet of black ink helps nobody. It goes wrong where the background is the content: a bar in a chart drawn as a colored box, a progress bar, a color swatch in a product listing, the stripes that keep a long table readable. The value exact tells the browser that the colors are "important and significant" and should be kept:
print-color-adjust became Baseline in May 2025, when Chrome and Edge 136 accepted it without a prefix; Firefox has had it since 97 and Safari since 15.4. Chromium and Safari supported the prefixed -webkit-print-color-adjust for years before that, so older guides use the prefix, and the deprecated color-adjust shorthand appears in older code too. One detail from MDN's compatibility notes for Chrome and Safari (Edge follows Chrome): they never print the background of the body element itself, even with exact; it applies only to the descendants. Put the color on an element inside.
And use exact sparingly. Every background it keeps costs the reader ink. The better fix is often a print design that does not need the background: a bar with an outline and a number, a badge with a border and a word, as in the demo's print sketch. Then exact is left for the few places where the color itself is what the reader printed the page for.
Ink subtracts
A screen adds light; ink on paper subtracts it, which How color works explained. A printer's gamut is a different shape from a screen's: usually smaller in the bright, saturated colors, especially vivid greens, blues and oranges, and its white is the paper. So saturated screen colors print duller, and a light tint can vanish into off-white paper. Colors that are close in lightness on screen can print as nearly the same gray on a black-and-white printer. None of this is under the page's control, and the browser's print path converts the colors for the printer as it does for any screen, so the habits are the same ones as for the room: margin, lightness differences, and a second cue for every state.
Print designers work in CMYK, the cyan, magenta, yellow and black of the press, and a brand guide often lists a CMYK or Pantone value beside the hex. Those are separate specifications, chosen for ink. Converting between them takes a profile for the particular press and paper, not a formula, so take the screen value from the guide rather than computing it from the CMYK numbers. CSS Color 5 defines a device-cmyk() function for print workflows, but no browser supports it as of October 2026; a browser prints from RGB. Tools that turn HTML into press-ready PDF, such as Vivliostyle and iText's pdfHTML, can read it.
Test with the browser's print preview, not with a guess, and use DevTools' option to emulate print media to inspect the print rules like any other styles.
12. Summary
| Concept | Key points |
|---|---|
| After the style sheet | A token is computed, converted to the screen's space and mapped into its gamut; then the panel, the room and the eye change it again. The page can ask about the first part and must plan margin for the second. |
| The gamut ladder | sRGB inside Display P3 inside Rec. 2020. P3 adds most to greens, reds and cyans and little to yellows and blues; most current phones and many laptops reach it. |
| Asking the screen | @media (color-gamut: p3) and (dynamic-range: high), or matchMedia() with a change listener; both widely available. They test browser and screen together: Firefox always reports sRGB because it draws CSS colors in sRGB. @supports tests only parsing. |
| Wide gamut, progressively | Strategy 1: a high-chroma oklch() token, mapped by the browser on sRGB screens; fine for decoration. Strategy 2: an sRGB token first, a P3 token inside @media (color-gamut: p3); for anything that must match. |
| Gamut mapping in practice | CSS Color 4 asks for chroma reduction at constant lightness and hue; Chrome 156 and WebKit clip each channel, which can shift lightness and hue far outside the gamut. Near the edge both agree, so keep chroma moderate for colors that must match, and check contrast on what is drawn. |
| Images | Tagged images (ICC profiles, PNG's cICP) are converted by the browser; untagged images are sRGB. Keep profiles, or convert before stripping them. |
| HDR | dynamic-range: high is widely available. dynamic-range-limit caps HDR brightness: Chrome 136, Safari 26 per MDN, not Firefox. The CSS Color HDR module is a Working Draft (26 October 2026). |
| The screen itself | Brightness, calibration, gamma (Mac 1.8 against Windows 2.2 until 2009), age and viewing angle change the color before the room does, and no media feature reports them; plan margin and check on more than one screen. |
| The room | Sunlight and projectors shrink contrast; night shift and True Tone warm the white point; grayscale and e-ink remove hue. light-level was removed from Media Queries in 2020 and never shipped. Aim well above 4.5:1 and let lightness and a second cue carry meaning. |
monochrome | Matches monochrome devices and printers; a hint, never set by grayscale accessibility filters. |
Backgrounds are dropped by default (print-color-adjust: economy); use exact only where color is the content. On body it applies to the descendants, but Chrome and Safari never print the body's own background. Ink subtracts, so saturated colors print duller. |