OKLCH Studio · Guides
What is OKLCH? Lightness, chroma and hue explained
Updated 2026-10-17
OKLCH is a way of writing a colour as three numbers: how light it is, how colourful it is, and which hue it has. That sounds like HSL, and the shape of the idea is similar, but the numbers behave very differently. In OKLCH, two colours with the same lightness value look about equally light to a person, whatever their hue. That one property is why designers and CSS authors have moved to it so quickly.
This guide explains what each of the three channels means, where the colour space comes from, and how it relates to the screens we actually use. It also covers the part that surprises people most: some OKLCH values describe colours a normal display cannot show, and software has to decide what to do about that.
OKLCH in one paragraph
OKLCH is the cylindrical form of Oklab, a colour space published by Björn Ottosson in December 2020. Oklab was designed so that equal numeric steps give roughly equal perceived steps in lightness, chroma and hue. OKLCH takes Oklab's two colour axes and rewrites them as an angle (hue) and a distance from grey (chroma), which is far easier for a person to reason about. CSS Color Module Level 4 defines both oklab() and oklch() as functions you can use directly in a stylesheet, so there is nothing to compile or convert at build time.
In CSS it looks like this: oklch(0.62 0.21 260) is a saturated blue, oklch(0.62 0.05 260) is the same blue with most of its colour taken out, and oklch(0.9 0.05 260) is a pale tint. Change one number and you change one thing you can describe in words. That is the whole appeal.
Lightness, chroma and hue
Lightness (L) runs from 0 (black) to 1 (white). In CSS you may also write it as a percentage, where 100% equals 1. It is a perceptual measure, not a measure of light energy: a mid grey sits near 0.6 rather than 0.5, because the scale follows how bright things look to us. This is the channel that matters most for readable text, and it is the one the contrast fixer on this site moves.
Chroma (C) is how far the colour is from a neutral grey of the same lightness. Zero is pure grey. There is no hard upper limit in the maths, but real colours on common screens stay below roughly 0.4, and most interface colours live between 0 and 0.25. Chroma is not the same thing as HSL saturation: it is an absolute amount of colour, so a pale pastel and a deep navy can have the same chroma and look nothing alike in vividness.
Hue (H) is an angle from 0 to 360 degrees around the colour wheel. In OKLCH a pure sRGB red sits near 29 degrees, yellow near 110, green near 142, cyan near 195, blue near 264 and magenta near 328. These are the values the repo's own conversion code returns for the six HSL primaries and secondaries, and they are not evenly spaced, which is a reminder that the wheel follows perception rather than RGB arithmetic. When chroma is close to zero, hue stops meaning anything, because every grey is the same grey.
A concrete case shows how these fit together. Tailwind CSS v4 defines its blue family with a single hue and a smoothly changing lightness: blue-50 has an OKLCH lightness of 0.970 and blue-950 has 0.282, with ten steps in between. You can read the lightness of any step straight off the number instead of eyeballing a swatch.
Where OKLCH comes from
Colour scientists have been building perceptual colour spaces for a century. The one most designers met first was CIELAB, with its polar cousin CIELCH. CIELAB is a real improvement over RGB, but it has well-known flaws: hues drift as lightness changes, and the most famous symptom is that blues turn purple when you lighten or darken them. Gradients and tints built on it can look subtly wrong.
Björn Ottosson's Oklab, published in 2020, was fitted to modern perceptual data with the aim of fixing exactly those problems while staying cheap to compute: a pair of matrix multiplications and a cube root. It predicts perceived lightness, chroma and hue better than CIELAB for the cases that matter to image and interface work, and it keeps hue far more stable when you change lightness. It is not a perfect model of vision, and nothing is, but it is good enough that browsers, Tailwind, and many design tools adopted it.
Oklab itself uses three Cartesian coordinates: L, and two colour axes called a and b. OKLCH converts the pair (a, b) into polar form. Chroma is the length of that vector and hue is its angle. Nothing is lost in the conversion; the two spaces describe exactly the same colours, and you pick whichever is more convenient. For mixing and gradients Oklab's axes are fine. For picking and adjusting colours by hand, OKLCH's three named channels are easier.
- Oklab: Cartesian, good for blending colours and measuring distances between them.
- OKLCH: polar, good for choosing a hue, then adjusting lightness and chroma independently.
- Both are defined in CSS Color Module Level 4 as
oklab()andoklch().
Why it suits design systems
A design system is mostly a set of rules about relationships: this surface is one step lighter than that one, this hover state is a bit darker, the text on it must be readable. Those rules are easy to state in OKLCH because lightness means the same thing in every hue. You can define a ramp once, with lightness values spaced evenly, and apply it to your blue, your green and your red, and the steps will line up visually across all three.
It also makes accessibility work more systematic. WCAG contrast depends on relative luminance, which is related to, but not identical with, OKLCH lightness. They are close enough that moving lightness is the natural way to repair a failing colour while keeping its hue and chroma. That is the approach the contrast checker on this site uses, and it is explained step by step in the guide to fixing colour contrast.
For a direct comparison with the colour model most people know already, read OKLCH vs HSL, which uses computed numbers rather than claims.
Gamut: sRGB, Display P3 and colours your screen cannot show
A gamut is the range of colours a display or a colour space can represent. Most websites are authored for sRGB, the baseline for the web since the 1990s. Many current phones, laptops and monitors can show Display P3, a wider gamut with noticeably more saturated reds and greens. Even wider spaces exist for professional video and photography.
OKLCH is not tied to any one display gamut. It is a model of colour perception, and it can describe colours outside sRGB and even outside P3. Because the channels are independent, you can write oklch(0.7 0.3 150) without anything stopping you, but no real screen can produce that green. The table below checks six values against the two gamuts using the code that powers this site's converters.
| oklch() | Smallest gamut | Chroma after mapping to sRGB | sRGB hex |
|---|---|---|---|
| oklch(0.700 0.100 150.0) | sRGB | 0.100 | #6FB07D |
| oklch(0.700 0.200 150.0) | Display P3 | 0.197 | #00BF54 |
| oklch(0.700 0.300 150.0) | wide | 0.248 | #00CB00 |
| oklch(0.600 0.250 30.0) | Display P3 | 0.247 | #F10000 |
| oklch(0.500 0.300 265.0) | wide | 0.289 | #1034FF |
| oklch(0.900 0.200 100.0) | Display P3 | 0.187 | #FEDF00 |
5 of these 6 sample colours are outside sRGB. Only the one with low chroma fits. The third column shows the chroma that remains after the colour is mapped into sRGB, and the last column shows the hex you would get. The hue and lightness are kept; the colour is simply made less vivid until it fits.
Clamping and gamut mapping
When a colour is out of gamut, there are two broad strategies. The crude one is clipping: convert to RGB and force any channel that is below 0 or above 1 back into range. It is fast but it can change hue and lightness, because each channel is clipped independently. A saturated cyan that is slightly out of range can come out visibly different.
The better strategy is gamut mapping, which keeps lightness and hue and reduces chroma until the colour fits. CSS Color Module Level 4 describes a gamut-mapping algorithm of this kind that works in OKLCH, and the converters on this site use the same idea: they hold L and H and pull C down. The effect is that an out-of-range colour turns into the most vivid in-range colour with the same lightness and hue, which is usually what a designer wants.
Two practical consequences follow. First, a hex code made from an out-of-gamut colour is an approximation, and converting it back will not return the original chroma. The converter pages show gamut information for each colour. Second, when you set a colour in CSS on a wide-gamut screen, the browser can display colours that the hex fallback cannot, so the two may differ slightly. That is expected and is the reason to keep a fallback at all; the OKLCH in CSS guide shows how.
What OKLCH does not do for you
OKLCH makes colour choices more predictable, but it does not make them automatically accessible. A pair of colours with a large lightness gap is likely to have good contrast, yet the only way to know is to measure it with the WCAG formula or another contrast method. OKLCH lightness is a perceptual coordinate. WCAG's ratio is computed from relative luminance, and the two disagree in places, especially in saturated blues and yellows.
It is also not a drop-in replacement for every workflow. Image formats, older design tools and some email clients only understand hex or RGB, so you still need conversions. The HEX to OKLCH converter and the OKLCH picker on this site exist for that reason: you can move a colour between notations and see its OKLCH values and whether it fits sRGB.
Finally, interpolation matters. Mixing two colours in OKLCH takes a path through hue, which can pass through colours you did not expect when the two hues are far apart. CSS lets you choose how the hue travels, and the guide to using OKLCH in CSS covers that.
FAQ
- What does OKLCH stand for?
- OKLCH is the polar form of Oklab. The letters name the three channels: L for lightness, C for chroma and H for hue. Oklab is the perceptual colour space published by Björn Ottosson in 2020, and OKLCH rewrites its two colour axes as a distance from grey and an angle.
- Is OKLCH the same as LCH?
- No. The older CIE LCH is built on CIELAB, which has known hue-shift problems, for example blues drifting toward purple as you change lightness. OKLCH is built on Oklab, which was designed to keep hue steadier. CSS has separate functions for them, lch() and oklch(), and the numbers are not interchangeable.
- What is a typical chroma value?
- Chroma is zero for greys. Interface colours are mostly below about 0.25, and colours on common screens rarely go past about 0.4. Values that are in range for Display P3 can be out of range for sRGB, so a highly saturated value may be shown with reduced chroma on a standard display.
- Can OKLCH show more colours than hex?
- OKLCH can describe colours outside sRGB, which hex cannot. Whether you see them depends on your display and browser. On an sRGB-only screen they are mapped into the displayable range, so the extra colours only matter on wide-gamut displays such as Display P3.
- Does OKLCH lightness equal WCAG contrast?
- They are related but not the same. OKLCH lightness is a perceptual measure, while the WCAG 2.x contrast ratio is calculated from relative luminance. They usually move together, which is why changing OKLCH lightness is an effective way to fix contrast, but you should always measure the final pair.
Try it
Pick a colour by its lightness, chroma and hue, see whether it fits sRGB, and copy it as oklch(), hex or a Tailwind value.