CSS oklch() Syntax: Lightness, Chroma, Hue & Alpha
oklch() takes three values — Lightness, Chroma and Hue — optionally followed by a slash and an alpha value. This page is the complete syntax reference: what each slot accepts, how the parts interact, and the patterns that keep older browsers working.
Last updated: 2026-10-07 · Maintained by the OKLCH Colors team
oklch() Syntax at a Glance
The function has one required form and one optional addition — the alpha channel, which appears after a slash rather than as a fourth space-separated value:
color: oklch(62.3% 0.188 259.8);
color: oklch(0.623 0.188 259.8); /* decimal form — identical */
color: oklch(62.3% 0.188 259.8 / 0.4); /* with alpha */
color: oklch(62.3% 0.188 259.8 / 40%); /* alpha as percent */The three space-separated values must appear in exactly that order — L, then C, then H. There is no named-argument form and no default for any of them; a value that could not be parsed invalidates the whole declaration, which is why an unsupported or malformed oklch() line falls through to the previous declaration rather than rendering a broken color.
What Each Value Accepts
| Slot | Accepted forms | Range & meaning | Example |
|---|---|---|---|
| Lightness | percentage or number | 0% (black) – 100% (white). 0.623 and 62.3% are the same value. | 62.3% |
| Chroma | number (with optional %) | 0 is neutral gray; saturation increases with the value. Typical sRGB colors sit between 0 and about 0.4. | 0.188 |
| Hue | angle — number or deg | 0–360° around the color wheel. Values wrap: 390 is the same hue as 30. | 259.8 |
| Alpha (optional) | after a slash — number or % | 0 (transparent) – 1 (opaque). 0.5 and 50% are equal. | / 0.5 |
Lightness is a percentage or its decimal equivalent. 50% and 0.5 parse to the same lightness — the percentage form is the one you will read in documentation and the one this site's converters emit, because it maps directly onto the 0–100% scale the value is described in.
Chroma is not a percentage of anything. It is an absolute distance from the neutral axis, so 0.1 in a dark color and 0.1 in a light color carry the same absolute colorfulness — but the dark color will look duller because low lightness limits how much chroma the eye resolves. The maximum chroma a lightness/hue pair can hold before leaving the sRGB gamut varies across the wheel; roughly 0.4 is the outer bound for sRGB.
Hue wraps, it does not clamp. oklch(70% 0.15 390) is perfectly valid and identical to oklch(70% 0.15 30). Negative hue values wrap the other direction. This matters in relative color syntax, where a calculation can easily push the angle past 360.
Alpha and the Slash
Transparency is the one optional part, and it always follows a slash. This matches the syntax rgb() and hsl() adopted in CSS Color Level 4, so an existing rgb(59 130 246 / 40%) converts to OKLCH by swapping the function name and the first three values:
.overlay {
background: rgb(59 130 246 / 40%);
background: oklch(62.3% 0.188 259.8 / 40%);
}Alpha compositing is unchanged from other color functions: two layers at 50% opacity stack to 75% coverage, and currentColor, inherit and custom-property substitution all behave the same way they do for any other color value.
Relative Color Syntax
With oklch(from ...) the function takes an existing color apart and rebuilds it channel by channel. Inside the brackets, the source color's own l, c and h are available as free values, which makes derived colors one line of CSS instead of a hand-computed second value:
/* Lighter by 10 percentage points of lightness */
color: oklch(from var(--brand) calc(l + 0.1) c h);
/* Shifted 30 degrees around the wheel */
color: oklch(from var(--brand) l c calc(h + 30));
/* Desaturated to 60% of its original chroma */
color: oklch(from var(--brand) l calc(c * 0.6) h);
/* Fully transparent version of the same color */
color: oklch(from var(--brand) l c h / 0%);This is the pattern behind most OKLCH design-system tricks — hover states, tonal ramps, and derived overlays — because it changes exactly one perceptual channel and leaves the others untouched. A HEX-based equivalent cannot do this: its channels do not map to perception, so "same color, a bit lighter" is guesswork.
Gradients: Choosing the Interpolation Space
A gradient between two OKLCH colors does not automatically interpolate in OKLCH — you choose the space explicitly with the in keyword. Specify it and the ramp travels through perceptually even color, avoiding the gray, muddy midpoint that channel-by-channel RGB interpolation produces between saturated colors:
.sunset {
background: linear-gradient(in oklch, oklch(65% 0.2 25), oklch(55% 0.18 290));
}The same in keyword works in conic-gradient(), in color-mix() (e.g. color-mix(in oklch, red 30%, blue)), and in the CSS transition of custom properties registered with @property — the four places where colors get blended.
Progressive Enhancement Patterns
oklch() is a Baseline feature (see browser support below), so fallbacks are belt-and-braces rather than daily necessity. Two patterns cover the remaining edge cases — a stale browser and a feature query for code that must not even ship when support is missing:
1. Cascade override — the browser picks the last declaration it understands:
.button {
color: #3b82f6; /* older browsers */
color: oklch(62.3% 0.188 259.8); /* modern browsers */
}2. @supports — gate everything OKLCH-specific, including derived rules:
@supports not (color: oklch(0% 0 0)) {
.button { color: #3b82f6; }
.hero { background: linear-gradient(#f97316, #7c3aed); }
}Because an unparsable color invalidates only its own declaration, pattern 1 works even when the fallback and the OKLCH value sit on the same property. Pattern 2 is the right tool when the OKLCH path also carries rules a legacy browser should not receive — relative color syntax, color-mix(), or wide-gamut gradients.
Out-of-Gamut Values
OKLCH can describe colors that no sRGB screen can display. When a value falls outside the display's gamut, the browser maps it to the nearest displayable color: on an sRGB display the result is subtly compressed toward the edge of the gamut, while a wide-gamut Display-P3 display shows more of the original chroma. The syntax is the same either way — out-of-gamut is a rendering concern, not a parse error, so the declaration stays valid.
If you need the exact in-gamut value before it ever reaches a browser — for a code review, a token file, or a tool that only reads HEX — clamp it with a converter rather than eyeballing it. Our OKLCH to HEX, OKLCH to RGB and OKLCH to HSL converters all reduce chroma to the nearest in-gamut color while preserving lightness and hue.
Browser Support for oklch()
oklch() is Baseline widely available: per MDN it has been supported across Chrome, Edge, Firefox and Safari since May 2023. Every syntax described on this page — including relative color syntax where supported, in oklch interpolation, and the slash alpha form — parses in current browsers.
Verified source: MDN — oklch() browser compatibility
Frequently Asked Questions
What is the correct order of values in oklch()?
Lightness first, Chroma second, Hue third — always space-separated — with an optional slash and alpha value at the end: oklch(L C H / A). There is no alternative ordering and no named parameters.
Do lightness values have to be percentages?
No. oklch(0.623 0.188 259.8) and oklch(62.3% 0.188 259.8) are identical — the number form is simply the same value written 0–1 instead of 0–100. The percentage form is more common in documentation because the scale is described in percent.
How do I write transparency in oklch()?
Add a slash after the hue, then an alpha number or percentage: oklch(62.3% 0.188 259.8 / 0.4) or ... / 40%. The slash form is required — a fourth space-separated number is not valid syntax.
Why does my oklch() declaration seem to do nothing?
An unparsable color invalidates only that declaration, so the browser falls back to the previous one (or the inherited value). Typical causes: a missing value, a comma instead of a space separator, or the alpha without its slash. Commas are the old CSS Color 3 syntax and are not accepted in oklch().
Can I interpolate between two oklch() colors in a gradient?
Yes — state the interpolation space explicitly: linear-gradient(in oklch, ...). The same in oklch keyword works in color-mix() and conic gradients, and produces evenly spaced ramps without muddy midpoints.
Practice: Convert a Color
Syntax sticks fastest with real values. Convert a color you use every day into oklch() and read the L, C and H numbers back off the reference table above: