What L, C and H Become in RGB
Each part of an oklch() value describes appearance, and none of them maps to a single RGB channel:
- L, lightness (0–100%, or 0–1) — raising it makes the colour lighter, which generally lifts the channels, by amounts that depend on the hue.
- C, chroma (0 upwards) — at 0, red, green and blue are equal and the result is a grey. The higher C, the further apart the channels.
- H, hue (0–360°) — decides which channels lead: around 30° red does, around 140° green, around 265° blue.
The default, oklch(72% 0.15 160), is a mid-light green with moderate chroma. Green leads and red trails, giving rgb(47, 193, 131).
OKLCH vs RGB: When Each Is Useful
OKLCH is the format to choose colours in. Its lightness tracks what the eye sees, so equal L means equally light; a palette stepped in L at fixed C and H keeps its hue; and it can name wide-gamut colours outside sRGB.
RGB is the format most other code consumes:
- canvas drawing, WebGL and image processing work in red, green and blue values;
- charting libraries, native apps and older stylesheets often accept nothing else;
- an rgb() value is an exact instruction to a standard screen, useful for screenshots and QA checks.
Converting at the boundary keeps both: tokens authored in OKLCH, and rgb() wherever a tool expects it. Going the other way, the RGB to OKLCH converter turns sampled values into oklch().
Using oklch() in CSS With rgb() Alongside
In a stylesheet, the rgb() result is a fallback written before the oklch() value:
.success {
background: rgb(47, 193, 131);
background: oklch(72% 0.15 160);
}In JavaScript, a canvas or charting call usually wants the rgb() string, while CSS custom properties can stay in OKLCH:
ctx.fillStyle = 'rgb(47, 193, 131)'; // converted value
element.style.setProperty('--success', 'oklch(72% 0.15 160)');A canvas fillStyle takes the same colour syntax as CSS in a browser that supports oklch(), but charting libraries and native code may not, so rgb() is the safe default outside stylesheets.
Browser Support
oklch() is supported in Chrome and Edge 111+, Safari 15.4+ and Firefox 113+. An older browser skips the oklch() declaration and keeps the rgb() line above it, so the fallback pattern needs no feature detection.
OKLCH to RGB Reference Values
These oklch() values, computed at build time, give white, black, the three sRGB primaries and this site's brand purple. Each is inside sRGB, so it converts to whole channel values exactly.
| Colour | oklch() | rgb() | HEX |
|---|---|---|---|
| White | oklch(100% 0 0) | rgb(255, 255, 255) | #FFFFFF |
| Black | oklch(0% 0 0) | rgb(0, 0, 0) | #000000 |
| Red | oklch(62.8% 0.25768 29.23) | rgb(255, 0, 0) | #FF0000 |
| Green | oklch(86.64% 0.29483 142.5) | rgb(0, 255, 0) | #00FF00 |
| Blue | oklch(45.2% 0.31321 264.05) | rgb(0, 0, 255) | #0000FF |
| Brand purple | oklch(64.57% 0.23988 316.07) | rgb(196, 78, 237) | #C44EED |
By contrast, oklch(90% 0.12 300) is outside sRGB: gamut mapping gives rgb(230, 210, 255) and clipping gives rgb(234, 204, 255).
How We Calculate
Chroma and hue become OKLab's a and b axes, which go through the inverse of the matrices from Björn Ottosson's OKLab article to linear sRGB, and then through the sRGB gamma curve (D65 white point) to values from 0 to 255.
If any channel falls outside 0–255 by more than 0.02 of a level, the colour is gamut-mapped with the CSS Color 4 algorithm: a binary search on chroma at constant lightness and hue, to a resolution of 0.0001, that stops when clipping changes the colour by less than 0.02 in OKLab. The hue of the result can therefore differ from the input by a few degrees. Channels are then rounded to whole numbers, and alpha is passed through to 3 decimals.
The Pantone panel compares the resulting RGB colour with weighted RGB ranking, as our Pantone converters do, and its matches are approximate.