Guide

sRGB, Display P3 and OKLCH

Why the same hex code looks different on two screens, and when the newer colour spaces are worth the trouble.

Last updated 25 August 2026

#ff0000 does not name a colour. It names three numbers. What colour those numbers produce depends on a colour space (a definition of what "full red" physically means), and a modern machine has more than one in play.

A colour space is a set of rules

Three things have to be agreed before three numbers mean anything:

  • The primaries. Exactly which red, green and blue the maximum of each channel refers to.
  • The white point. What the three at full strength together should look like. This is usually D65, a daylight white.
  • The transfer function. How stored numbers map to emitted light. sRGB uses a curve of roughly 2.2, which is why 128 is not half as bright as 255.

Change the primaries and the same numbers describe a different colour. That is the whole story behind "it looked different on my other monitor".

sRGB is the assumption

sRGB was standardised in 1996 to describe what a typical CRT monitor of the time could produce. It is narrow by modern standards, and it is still the default assumption almost everywhere: an untagged image, an unqualified hex code in CSS, and most of the web are all treated as sRGB.

That ubiquity is its strength. A colour specified in sRGB looks approximately right on anything, because everything either is sRGB or knows how to convert to it.

Display P3 is wider

Most phones and laptops sold in the last several years cover Display P3, a gamut roughly 25% larger than sRGB, mainly in the greens and reds. Saturated colours that sRGB simply cannot represent are available on those screens.

CSS can reach them:

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

That is a red more saturated than #ff0000 on a P3 display, and it falls back sensibly on an sRGB one. Useful for a brand colour that has always looked slightly flat on screen, and for photography.

This is also where a colour picker meets its limit. If an image carries a P3 profile, your browser converts it for display, and different browsers and operating systems do not always convert identically. ColorFinders reports what your browser decoded. That is the right answer for web work, and not the right answer for print production.

OKLCH is a different kind of improvement

P3 widens the range of colours. OKLCH does something else entirely: it makes the numbers behave.

In HSL, hsl(60 100% 50%) is a brilliant yellow and hsl(240 100% 50%) is a very dark blue, yet both claim 50% lightness. That makes HSL almost useless for generating a consistent ramp, because equal numeric steps are not equal visual steps.

OKLCH fixes this. Its three components are:

  • L: perceptual lightness, 0 to 1. Equal steps look equal.
  • C: chroma, how colourful. Not capped at 100; it depends on the hue.
  • H: hue angle, 0 to 360.

The practical payoff: hold C and H, step L evenly, and you get a ramp where every step is the same size and the hue does not drift. Do the same in HSL and blues turn purple as they darken. This is why design systems have been migrating to it.

OKLCH also describes colours outside sRGB, so it works as a single notation for both sRGB and P3 output. And interpolating in OKLab (its rectangular form) avoids the muddy midpoints that sRGB blending produces, which the colour mixer demonstrates directly.

Which to use

SituationUse
Sharing a value, pasting into a design toolHex
Generating a lightness rampOKLCH
Interpolating or mixingOKLab
A saturated brand colour that looks flatDisplay P3, with an sRGB fallback
Measuring how different two colours areCIE Lab, via ΔE
Anything that must work everywhere unchangedsRGB
PrintNeither: use a colour-managed application with an ICC profile

Why your screenshot does not match

The common frustrations, and their causes:

The same hex looks different on two monitors. One is probably a wider gamut than the other, or is not calibrated. Both are showing you their interpretation of sRGB.

A sampled colour does not match the design file. The image likely carries a profile that was converted on the way to your screen. Sample in the application that owns the profile if it has to be exact.

A screenshot is warmer than the original. A night-shift or blue-light filter was probably active when it was taken. The screenshot records what was composited to the display, filter included.

CMYK does not match the print. This is expected. An uncalibrated conversion has no profile for the press, ink or paper. It is a starting point, and this site labels it as one.

For everyday web work, none of this needs to change what you do: specify in sRGB, generate ramps in OKLCH, and sample with the image picker when you need an exact value out of a picture.