
There's a selected type of frustration that every designer knows. You spend 40 mins landing on precisely the right blue — the one that communicates calm with out tipping into cold, that works against the off-white history without going grey, that holds its weight at small sizes without going muddy. You export it. You hand it off. And then you see it on a person else's display screen and it's far simply barely, undeniably incorrect.
Not incorrect in a way you can explain effortlessly. Wrong in the way that makes you wonder if you are dropping your thoughts or your eye. Incorrect in the manner the purchaser's projector makes your cautiously calibrated teal seem like clinic scrubs. Wrong within the manner your logo crimson looks heat and assured on your MacBook and slightly competitive on the home windows machine in the conference room.
The trouble isn't your eye. The trouble is the coordinate device you're the use of to describe colour. And once you understand what HEX codes genuinely encode — and what they absolutely forget about — the motive every cross-device color hand-off has a small hazard of going incorrect becomes obvious.
What a HEX Code truely Says
A HEX colour code is a base-16 (hexadecimal) illustration of 3 integers, each ranging from zero to 255, that instruct a display device how a lot voltage to send to the purple, inexperienced, and blue subpixels at a given location. Nothing more.
#FF0000 breaks down as: FF = 255 in decimal, meaning maximum drive sign to crimson subpixels. 00 = 0, that means no signal to green subpixels. 00 = zero, which means no signal to blue subpixels.
It's miles a hardware preparation. The assertion it makes is: pricey show, please force your crimson subpixels at complete energy and go away the others off. This is the entire, general semantic content material of a HEX colour code.
What the human looking at that show really sees is determined by means of some thing else entirely — the bodily traits of the display's subpixels, its white point, its gamma curve, its peak luminance, its panel type, the ambient lights in the room, and the visual gadget of the particular person doing the searching.
The 3 matters HEX Does now not Encode
Absolute luminance. #FFFFFF on a dim workplace projector produces more or less 300 candelas in line with square meter (nits) of white. The identical #FFFFFF on an iPhone sixteen pro in out of doors brightness mode produces 2,000 nits. The HEX is equal; the real light output differs by way of 6.6x. Any color expressed as a HEX cost will seem lighter or darker depending at the display's most brightness — and there may be no way to explicit that within the HEX code itself.
The coloration of the primaries. Each display has red, inexperienced, and blue subpixels, however red is not a common general. A purple OLED subpixel and a crimson LCD backlit subpixel produce extraordinary wavelength distributions. #FF0000 on a huge-gamut P3 display produces a without a doubt specific shade — a greater saturated, slightly special hue — than #FF0000 on a widespread sRGB display. The code is the identical; the photons are different.
The gamma and white point. The relationship between the numeric price sent to a show and the luminance it outputs is nonlinear, governed via the gamma curve. sRGB makes use of an approximately 2.2 gamma. A few older presentations shipped with 1.8 gamma. The white point — the colour of maximum white — is nominally D65 (6500K) for sRGB but varies by means of panel calibration. Both of those have an effect on how each intermediate color value is rendered.
The equal HEX on five actual screens
To make this concrete: what does #E8532A — a warm, mid-saturation orange — seem like throughout actual production hardware?
| Display | Panel Type | Shade Gamut | Top Luminance | Perceived Result |
|---|---|---|---|---|
| MacBook seasoned 16 M4 | Liquid Retina XDR | DCI-P3 extensive | 1,000 nits (SDR: 500) | Warm, vivid, slightly punchy orange |
| Dell UltraSharp U2723D | IPS liquid crystal display | sRGB a 100% | 400 nits | Correct, slightly flatter orange |
| Samsung Galaxy S25 ultra | AMOLED | DCI-P3 wide | 2,600 top | Exceptionally extra saturated, punchier |
| finances 1080p office monitor | TN lcd | sRGB 72% | 250 nits | Noticeably muted, barely brownish |
| Epson EB-L series projector | 3LCD | sRGB 85% | 300 nits pondered | Desaturated, cooler, looks as if terracotta |
| Apple vision pro | Micro-OLED | P3 huge | 5,000 nits height | Wealthy and tremendously saturated — maximum vivid rendering |
Six devices. One HEX code. Six perceptually exclusive colorings. None of them is incorrect — each tool is faithfully executing the education #E8532A within its personal hardware constraints. The HEX code is only a blind coordinate: it factors at a location in an abstract three-dimensional cube and trusts that each device's cube is the identical shape.
Why Human imaginative and prescient Makes This Worse
The display-hardware problem would be horrific sufficient on its own. However human notion adds another layer of complexity that pure hardware calibration can't remedy.
Simultaneous contrast: The Enemy of Flat color wondering
Hues do now not exist in isolation for human imaginative and prescient. The identical shade patch seems lighter on a darkish background and darker on a light heritage — an impact called simultaneous lightness assessment. Two equal HEX greys placed on black and white backgrounds might be perceived as distinct sunglasses even though the encoded values are identical.
Hue assessment works the same way. A impartial gray surrounded by way of a heat history shifts slightly cool. The same grey surrounded via a fab heritage shifts slightly warm. The HEX price #808080 has now not changed, the visible system has.
This subjects for UI layout due to the fact the colour you pattern from a palette or spec sheet is in no way evaluated in isolation — it's far always evaluated against adjoining colorings, backgrounds, and the ambient surroundings. A brand blue that assessments flawlessly against white in isolation may additionally read in a different way towards the dark card backgrounds in a darkish-mode format the use of the identical HEX cost.
The Perceptual Non-Uniformity of RGB
Here is the deeper structural hassle with the usage of RGB (and therefore HEX) for coloration layout decisions: equal numeric steps in RGB do no longer correspond to equal perceived color differences.
Bear in mind stepping from #000000 to #FF0000 in 5% increments. The perceptual leap among the first increment (close to-black to very darkish pink) is full-size — your eye right now sees the distinction. The perceptual leap between #F01010 and #FF0000 — numerically the same step length — is nearly invisible. The RGB dice is perceptually compressed in a few regions and stretched in others.
Nearly: in case you boom a color's brightness value by using 30 HEX gadgets, you don't have any way of knowing from the RGB coordinates whether or not that 30-unit exchange produces a barely great shift or a dramatic one. You need to look. The coordinates are not telling you.
That is the middle problem that a class of coloration areas called perceptually uniform coloration areas became invented to resolve.
CIE LAB: the first try at a Human Coordinate gadget
In 1976, the worldwide fee on Illumination (CIE) posted a colour space designed round human visual belief as opposed to show hardware. CIE LAB — generally written as L*a*b* or genuinely Lab — has 3 axes that attempt to without delay encode how people understand color differences as opposed to what indicators a display gets.
What L*, a*, b* sincerely mean
L* — Lightness. Runs from zero (perceptual black) to a hundred (perceptual white). seriously, L* is derived from the cube root of the physical luminance ratio, which approximately compensates for the nonlinear reaction of human vision to light. Same steps in L* are about same perceived lightness variations.
a* — The green-crimson axis. Terrible values are green; tremendous values are crimson. An a* of +60 is a vibrant red; an a* of -40 is a brilliant inexperienced; an a* of zero is neither.
b* — The blue-yellow axis. Terrible values are blue; nice values are yellow. Same shape as a*.
The coordinate (L*=50, a*=+60, b*=+40) describes a colour completely independently of any display tool. It does not say provide the show 255 red and eighty inexperienced. It says the color that a human observer with trendy imaginative and prescient might perceive as medium-lightness, surprisingly red-shifted, incredibly yellowish. Any display may be calibrated to breed this perceptual goal — and the LAB coordinate is what specifies the target.
The conversion from sRGB HEX to LAB goes through an intermediate step through a device-impartial absolute shade space referred to as CIE XYZ, which anchors the entirety to bodily radiometric measurements. The entire chain: HEX to linear RGB to XYZ to LAB.
Delta-E: Measuring shade distinction in Human gadgets
As soon as you have got shades in LAB, you may calculate Delta-E — the Euclidean distance among two LAB coordinates — which measures shade difference in about perceptual units.
| Delta-E value | What a Human Observer Perceives |
|---|---|
| 0.0 to 1.0 | Imperceptible — indistinguishable under everyday viewing |
| 1.0 to 2.0 | Perceptible handiest to a educated eye below managed conditions |
| 2.0 to 3.5 | great on direct comparison; perfect for most print |
| 3.5 to 5.0 | virtually visible difference; complicated for brand consistency |
| 5.0 to ten.0 | apparent to any observer — extraordinarily distinctive colorings |
| 10.0 and above | absolutely distinctive shades through notion |
This is what HEX cannot give you. The numeric distance between #FF0000 and #FE0000 — one unit in RGB — has no predictable perceptual meaning. In a few colour regions, a 1-unit change is invisible. In others, it's far the distinction among identifiably extraordinary colorations. Delta-E in LAB space gives you quite a number that absolutely maps to human perception. This is the fundamental improve.
Where LAB still Falls brief
LAB become a main increase, however it was designed in 1976 and calibrated against human notion statistics from that technology. Present day studies has revealed two persistent weaknesses.
Hue linearity. The a* and b* axes are not flawlessly linear for hue at excessive chroma (vivid saturation). Blues in LAB specifically have a properly-documented hue-rotation hassle: as you growth saturation along the b* axis, the perceived hue shifts towards crimson in preference to staying at a smooth blue. Designers working with brilliant blues or purples in LAB should account for this manually.
Chroma uniformity. Identical steps in chroma (how saturated a colour is) do not produce perfectly identical perceived saturation variations across all hue angles. veggies and yellows are compressed in comparison to reds and blues in approaches that require correction formulas. Delta-E 2000, as an instance, adds three weighting features to compensate for LAB's chroma non-uniformity.
Those limitations are why, in 2020, a brand new shade area emerged that addressed them.
OKLCH: The color area built for 2026 displays
OKLCH is a polar reformulation of the Oklab shade area posted with the aid of Bjorn Ottosson in 2020. It was in particular designed to repair the hue-linearity and chroma-uniformity troubles in LAB at the same time as retaining the tool-independence that makes LAB beneficial. CSS coloration level 4 — now supported in all most important browsers — consists of OKLCH as a nice colour price. It isn't a destiny era. it's miles available right now.
What OKLCH Fixes That LAB Did now not
OKLCH uses 3 coordinates: L (Lightness, from zero to 1), C (Chroma or saturation, from zero to more or less 0.37 for sRGB hues), and H (Hue angle, from zero to 360 tiers).
L — Identical idea as LAB's L*, but with advanced uniformity. Identical L steps produce greater continuously identical perceived brightness steps, in particular within the darkish and saturated areas in which LAB struggles.
C — 0 is completely achromatic (gray). Higher values are more saturated. Crucially, OKLCH's chroma axis is greater perceptually uniform than LAB's — same C steps produce greater identical perceived saturation steps across all colours.
H — Hue perspective in ranges. Crimson sits around 29 ranges, Yellow round 109, green around 142, Cyan round 194, Blue around 264, purple around 308. The hue attitude rotates through the shade wheel in a manner that is an awful lot extra perceptually linear than LAB's a* and b* Cartesian axes.
The blue hue-rotation hassle that plagues LAB is essentially solved in OKLCH. A vibrant blue at C=0.20 and H=264 stays perceptually blue as you regulate C — it does not slide towards red the way LAB blues do.
OKLCH in real CSS
OKLCH is the first color space wherein you can adjust character perceptual properties — lightness, saturation, hue — in isolation without the other homes drifting. The desk beneath shows a systematic logo palette built in OKLCH, and identifies exactly which unmarried coordinate changes each version from the base.
| CSS Token | OKLCH value | What modifications vs. Base |
|---|---|---|
| --emblem-blue | oklch(0.55 0.18 264) | Base price — medium blue |
| --logo-blue-tint | oklch(0.78 0.18 264) | L raised to 0.seventy eight simplest — lighter, hue and chroma locked |
| --brand-blue-coloration | oklch(0.35 0.18 264) | L diminished to 0.35 best — darker, hue and chroma locked |
| --logo-blue-muted | oklch(0.55 0.07 264) | C reduced to 0.07 most effective — desaturated, lightness and hue locked |
| --emblem-blue-complement | oklch(0.55 0.18 84) | H turned around 180 tiers — complementary orange, L and C locked |
Now strive doing the equal operations starting from #2B6CB0. To lighten it, you can not in reality add a hard and fast offset to each channel — the channels engage nonlinearly and the perceived hue will glide as you do it. You have to convert to HSL, adjust L, and convert lower back — and even HSL isn't always perceptually uniform, so you can't predict how a great deal the lightness will surely seem to trade.
The OKLCH workflow makes the connection among the coordinate and the notion express and solid.
The display Gamut problem: P3, Rec.2020, and past
Device-independence in LAB and OKLCH solves the notion hassle. however there may be a 2nd, parallel problem that HEX papers over: gamut — the range of colors a show can bodily reproduce.
What Gamut way and Why It Breaks HEX
A show's gamut is the set of all colorations it is able to produce by means of mixing its purple, green, and blue primaries. Because each show has extraordinary number one colorations (distinctive top wavelengths from its LEDs or OLEDs), every display's gamut is a distinctive-shaped vicinity of the visible color spectrum.
The sRGB gamut — designed in 1996 for CRT monitors — covers about 35% of the colours seen to the human eye (the CIE 1976 americashade space). DCI-P3, utilized in cutting-edge iPhones, MacBooks, and cinema monitors, covers approximately 54%. Rec.2020, the HDR television fashionable, covers approximately 75%. The human eye, under highest quality situations, can solve shades that none of these requirements attain.
A HEX shade written for sRGB — #FF0000, pure sRGB crimson — maps to a particular point within the seen spectrum. whilst that code is sent to a P3-capable show strolling in P3 mode, the display can reproduce colors beyond what the HEX variety became designed for. Depending on how the browser and OS deal with shade management, #FF0000 on a P3 display may be rendered as sRGB pink (efficiently contained within sRGB), or it can try and use the display's full P3 crimson primary — generating a highly greater bright purple than the fashion designer meant.
Gamut coverage with the aid of show kind
| Show class | Coloration widespread | Gamut vs. sRGB | Approx. % visible Spectrum |
|---|---|---|---|
| Budget TN/VA video display units | sRGB partial | 72 to 92% of sRGB | 25 to 32% |
| Popular IPS monitors | sRGB | 99 to 100% of sRGB | ~35% |
| MacBook seasoned, iPhone 16, iPad pro | DCI-P3 | ~133% of sRGB | ~54% |
| Samsung Galaxy S25, Pixel 9 seasoned | DCI-P3 / show P3 | ~130% of sRGB | 50 to 54% |
| Reference monitor (Eizo, NEC) | AdobeRGB | ~130% of sRGB | ~50% |
| HDR tv (Samsung QD-OLED) | Rec.2020 partial | 175 to 190% of sRGB | 65 to 70% |
| Apple vision pro | DCI-P3 | ~133% of sRGB | ~54% |
| Theoretical complete HDR show | Rec.2020 complete | ~220% of sRGB | ~75% |
The price range screen at 72% of sRGB coverage and the MacBook pro at 133% sRGB coverage sit down at contrary ends of a 1.85x range — nearly double the shade range. A bright orange you designed on a P3 show may additionally physically not exist on a 72% sRGB price range display. The show can not reproduce it. It's going to map that HEX to the closest shade it may display, which is the muted, barely exceptional version the customer at the finances display screen sees.
LAB and OKLCH are gamut-impartial via definition — they describe perceptual objectives which could or might not be inside any unique display's gamut. A color defined in OKLCH with a high chroma value can be out-of-gamut for sRGB but flawlessly renderable on P3. The designer can see this before hand-off, check the gamut boundary, and make an intentional selection — rather than coming across the gamut clip on the patron's screen.
The Conversion Chain: From HEX to LAB to OKLCH
Know-how the conversion chain topics because it famous in which the assumptions stay — and where move-device color accuracy virtually comes from.
| Step | From | To | What takes place |
|---|---|---|---|
| 1 | HEX (#RRGGBB) | sRGB (zero to at least one go with the flow) | Divide every channel by 255: #FF0000 turns into (1.0, zero.zero, zero.0) |
| 2 | sRGB | Linear RGB | reverse gamma: practice the sRGB piecewise transfer function inverse |
| 3 | Linear RGB | CIE XYZ (D65) | Multiply with the aid of a 3x3 matrix encoding the sRGB number one chromaticities |
| 4 | CIE XYZ | CIE LAB | observe cube-root compression with D65 white factor normalization |
| 5 | CIE LAB | Oklab | practice a 2nd linear matrix rework (Ottosson 2020) |
| 6 | Oklab | OKLCH | Convert Cartesian (a,b) to polar (C,H): C = sqrt(a2+b2), H = atan2(b,a) |
Step 2 — reversing gamma — is where most quick HEX-to-LAB converters make their first mistakes. sRGB does now not use a pure power-law gamma; it makes use of a piecewise function with a linear phase close to black. Skipping the exact transfer function and approximating with a easy 2.2 energy law introduces a measurable Delta-E blunders in darkish shades. For layout gear, this error is generally invisible. For print production matching, it could push a coloration beyond the Delta-E 2.0 perceptibility threshold.
Step 3 — encodes the single most essential assumption inside the whole chain: the sRGB primaries. The XYZ values produced by this matrix are most effective physically significant if the source show is calibrated to sRGB. An uncalibrated display, an lcd with aged backlight, or a display with wider primaries will produce exceptional XYZ values for the equal HEX code — that's why hardware calibration is the prerequisite for accurate shade management, now not the afterthought.
Why you still deliver HEX (but layout in OKLCH)
None of that is an issue for leaving behind HEX in manufacturing. HEX is the cutting-edge lingua franca of the net — it is compact, universally parseable, and supported everywhere. CSS browsers render it, layout equipment export it, builders paste it into code without a second idea.
The argument is set in which on your workflow the shade selections are made. When you are selecting a palette, constructing a layout machine, trying out whether or not two colors create enough assessment, verifying that a hover nation is detectably one of a kind from its base, or checking that your darkish-mode variants are perceptually regular with their light-mode equivalents — the ones selections should be made in OKLCH or LAB. The coordinates are telling you something actual about what you and your users will truly see.
When you are shipping, convert to HEX or to CSS oklch() values immediately (browsers take care of the gamut mapping for you). The output layout is an implementation element. The color choices are the substance.
The designer who specifies oklch(0.55 zero.18 264) and ships #2B6CB0 is making the same perceptual selection with specific focus of what the variety approach. The dressmaker who selections #2B6CB0 immediately is making the equal decision blindly — trusting that their display, their colleague's display screen, the purchaser's browser, and the production environment all agree on what that guidance produces. Increasingly more, they do no longer.
Realistic Workflow for cross-tool shade
The workflow shift is smaller than it sounds. It does not require rebuilding your design gadget or retraining your team on color technological know-how. It requires three centered changes.
Audit your palette in OKLCH or LAB earlier than locking it. Convert your present logo colours using a colour converter and examine the L* (lightness) values. in case your mild background and darkish textual content have L* values of 85 and 45, the contrast is predictable and robust throughout displays. In case your high-contrast button pair has a Delta-E of handiest 18, it may no longer be as legible because it appears for your calibrated reveal.
Generate systematic scales in OKLCH, now not HSL. HSL lightness isn't always perceptual — stepping from HSL L=40 to L=60 produces a visibly specific lightness jump in blue than in yellow, due to the fact the underlying shade area isn't always perceptually uniform. OKLCH L steps are steady across shades. A design device token scale generated in OKLCH will have visually even steps; the identical scale generated in HSL could have seen irregularities at sure hues.
Take a look at gamut limitations earlier than hand-off. Convert your most vivid hues (high-saturation brand shades, bright accents) to OKLCH and check their chroma values. Colours above about C=0.25 are in all likelihood outside sRGB gamut — that means they will be gamut-clipped on any display not strolling in P3 or wider mode. Recognise which shades are at threat before your customer sees them on a trendy screen.
The coordinate system you operate to describe coloration determines whether you're designing blindly or deliberately. HEX is the language of display instructions. LAB and OKLCH are the language of human belief. The translation between them is not lossy — it's far clarifying. The colour changed into usually going to seem like some thing on a real screen; knowledge the conversion simply approach you get to decide what it looks as if instead of being amazed through it.


