What Is OKLCH?
OKLCH is a way of writing colors in CSS that's built around how humans actually perceive color, rather than how a screen happens to store it. It's part of the CSS Color Module Level 4 spec, and every modern browser now understands it. If you've used the picker above, you've already seen it in action. Every value it generates, in that preview box, is an OKLCH color paired with a fallback for browsers that can't read it yet. Basically, the OKLCH box displays the OKLCH color, and the sRGB Fallback box displays the color that will be displayed in browsers that don't support OKLCH yet.
The OK prefix of the name indicates it is a variation of the Oklab color space. The LCH part stands for Lightness, Chroma, and Hue. Those three values control every color you can make with it, and they behave in a much more predictable way than the color models most developers grew up with. A CSS declaration using it looks like this.
.card {
background-color: oklch(78% 0.12 145);
}
That's a soft green. Bump the lightness up and it gets paler without shifting hue. Bump the chroma up and it gets more saturated without getting darker or lighter. That sounds obvious, but if you've spent any time with HSL you'll know it doesn't usually work that way. More on that in a moment.
Breaking Down the Four Values
An OKLCH color is made of three required numbers and one optional one:
| Value | Range | What It Controls |
|---|---|---|
| L (Lightness) | 0% to 100% | How light or dark the color is. 0% is always black, 100% is always white, regardless of hue. |
| C (Chroma) | 0 upward, practically 0 to around 0.4 | How saturated or vivid the color is. 0 is always grey. Higher numbers push toward the most vivid version of that hue. |
| H (Hue) | 0 to 360 degrees | The actual color, red, yellow, green, blue, and everything between. |
| Alpha | 0% to 100% (optional) | Transparency. Added after a forward slash, like oklch(78% 0.12 145 / 60%). |
Try adjusting each field in the picker above while watching what actually changes in the preview.
Chroma is usually the least intuitive for most people. This is mostly because it doesn't have a fixed maximum the way lightness and alpha do. How much chroma is actually available depends on the lightness and hue you've chosen. That's exactly what the diagonal, curved shape of the plane in the picker above is showing you. At very low or very high lightness, there's barely any room for saturation before you run out of representable color. In the middle, there's a lot more to play with. That's not a limitation of the tool, it's a real property of color itself.
Why Not Just Use HSL?
HSL also has a hue and a lightness value, so it's fair to ask why OKLCH is worth switching to. The short answer is that HSL was never built around how the eye actually works. It was built around how monitors store RGB values, dressed up to look more intuitive. The result is that HSL's lightness is only sort of accurate. A pure yellow at 50% lightness looks dramatically brighter than a pure blue at the same 50% lightness, even though HSL is telling you they're equal.
OKLCH fixes that. Two colors with the same L value will look equally light to a human eye, no matter what hue they are. This matters more than it might sound like at first. Say you're building a set of five status badges, success, warning, error, info, and neutral, and you want them all to feel like they belong to the same family with the same visual weight. In HSL, matching the lightness numbers often gets you colors that don't actually look consistent. In OKLCH, matching the lightness numbers gets you colors that genuinely do.
The same logic applies to generating a color scale. OKLCH is much more intuitive. Pick a hue, then create five or six steps by only changing the L value, and you'll get a smooth, evenly spaced set of shades with no unexpected jump in brightness partway through. That's a common trick for building things like button states or chart palettes, and it's far more reliable in OKLCH than it ever was in HSL.
OKLCH and Screen Limits
An important thing to be aware of is that OKLCH works independently of your screen's capabilities. OKLCH itself doesn't care what your monitor can actually display. You can type a chroma value far beyond what any screen can reproduce and the syntax is still perfectly valid, it's just describing a color that can't be shown accurately on the hardware in front of you.
This is why the picker above has three distinct zones baked into its color plane. Colors inside the thin boundary line are within sRGB, the color space that basically every screen ever made can display without issue. Colors between that line and the transparent edge fall inside Display P3, a wider gamut used by most phones and modern Macs, but not by every laptop or monitor out there. Anything past the transparent edge isn't something current consumer hardware can reproduce at all, on any device.
This means the further you push chroma, particularly in blues, purples, and greens, the more likely it is that only some of your visitors will see the color exactly as intended. Everyone else will see the fallback color instead, which brings us to the next part.
Browser Support and Writing Safe Fallbacks
Every browser released in the last few years supports oklch(), but plenty of visitors are still on older versions, and it costs nothing to guard against that.
The simplest approach relies on the cascade. Older browsers silently ignore any CSS declaration they don't understand, so you can just declare the fallback color first, followed by the OKLCH version. Anything unable to parse the second line keeps the first.
.button {
color: #3b82f6; /* fallback for older browsers */
color: oklch(62.3% 0.188 259.8);
}
The other approach wraps the OKLCH version in an @supports block, which is a little more explicit about what's happening and keeps your fallback and enhanced styles visually separate in the stylesheet.
.button {
color: #3b82f6;
}
@supports (color: oklch(0% 0 0)) {
.button {
color: oklch(62.3% 0.188 259.8);
}
}
Both approaches produce identical results in the browser, so the choice mostly comes down to how you like organizing your stylesheet. The picker above lets you flip between the two so you can copy whichever style fits your project.
Where OKLCH Actually Helps
It's easy to treat a new CSS color format as a novelty, so it's worth being specific about where OKLCH earns its place.
- Building color scales. Keeping hue and chroma fixed while stepping the lightness value gives you a set of shades that feel evenly spaced, which is much harder to pull off reliably in HSL or plain RGB.
- Gradients without the muddy middle. A gradient between two hues in RGB or HSL often passes through a dull, greyish patch partway through. Because OKLCH is perceptually even, gradients tend to transition more smoothly and stay visually interesting the whole way across.
- Matching visual weight across a palette. If you need a red, a green, and a blue that all feel equally prominent on the page, matching their L values gets you there. Matching lightness in HSL usually doesn't.
- Designing for wide-gamut screens on purpose. If your audience is mostly on newer devices, you can lean into Display P3 colors deliberately, knowing exactly which visitors will see the richer version and which will fall back gracefully.
A Few Quirks Worth Knowing About
OKLCH is a big improvement over older color models, but it isn't flawless. If you drag the picker above around the darker end of a blue or purple hue, you might notice the available chroma doesn't shrink in a perfectly smooth curve, it dips, expands slightly, then dips again. That's a real, documented quirk in the underlying OKLab model, not a rendering bug. It happens because the model's predicted hue drifts very slightly at different lightness levels for certain hues, which is enough to put a small wrinkle in the gamut boundary. You'll see the same behavior in other OKLCH tools, not just this one.
It's also worth remembering that "in gamut" isn't a single yes-or-no answer. A color can be perfectly valid in sRGB, valid only in the wider Display P3 space, or valid on no current screen at all, and the picker's three-zone plane is designed to make that distinction visible rather than hide it behind a single fallback color.
None of that makes OKLCH harder to use day to day. For almost everything you'll build, picking a hue, adjusting lightness for shades, and nudging chroma for intensity is a far more direct way of working with color than juggling RGB values or fighting with HSL's uneven brightness. The picker above is meant to make that hands-on, so it's worth spending a few minutes just dragging things around and watching the numbers and the CSS output change together.