# OKLCH

> Lightness values that look equal.

- Section: Color
- URL: https://critly.vercel.app/oklch
- Published: 2026-07-14
- Source: https://github.com/kausthubh-coder/critly/blob/main/content/color/oklch.mdx

In HSL, lightness is a number the math likes and your eyes don't. A yellow at
65% looks bright and a blue at 65% looks far darker. **OKLCH** defines lightness the
way people see it, so one value looks about as light on every hue.

**Pick colors in OKLCH, so equal lightness numbers actually look equally
light.**

> **Interactive demo: Oklch.** Open https://critly.vercel.app/oklch to try it.

Switch to lightness only and the HSL row turns into uneven grays, while the
OKLCH row stays flat. That unevenness is why text passes contrast on one hue
and fails on the next, and why some badges look louder than others.

## The three numbers

`oklch(L C H)` is lightness, chroma and hue. Lightness runs from `0` (black)
to `1` (white). Chroma is how colorful it is, from `0` (gray) up to about
`0.32` in sRGB and `0.36` on a P3 screen. Hue is an angle: around `25` is
red, `145` green and `250` blue.

Change one number and only that thing changes. Set chroma to `0` and any hue
becomes a gray at the same lightness.

## Gradients

The color space also decides what happens between two colors. In sRGB, a
gradient between opposite hues runs straight through gray. In OKLCH it keeps
its chroma and turns through the hues in between.

> **Interactive demo: Oklch Gradient.** Open https://critly.vercel.app/oklch to try it.

You get this with one keyword: `linear-gradient(in oklch, ...)`.

## Palettes

Because lightness is reliable, a tonal scale is just a list of lightness
values on one hue. Drag the hue and the ramp keeps its shape.

> **Interactive demo: Oklch Palette.** Open https://critly.vercel.app/oklch to try it.

White text on the 700 step stays between 6.1:1 and 7.1:1 contrast on every
hue. White on `hsl(h 70% 50%)` swings from 1.5:1 to 8.9:1.

Hues can't all hold the same chroma, though. At lightness `0.93`, sRGB fits
a green with almost four times the chroma of a blue. The demo caps every step
at what sRGB can show, which is why some hues come out softer.

## Usage

Tailwind v4 already defines its palette in OKLCH, and the color tokens on
this site are all OKLCH too.

**Tailwind**

```html
<button class="bg-[oklch(0.48_0.13_250)] text-white hover:bg-[oklch(0.38_0.1_250)]">
  Continue
</button>

<span class="bg-[oklch(0.93_0.05_145)] text-[oklch(0.48_0.12_145)]">
  Shipped
</span>
```

**CSS**

```css
:root {
  --brand-200: oklch(0.93 0.03 250);
  --brand-700: oklch(0.48 0.13 250);
  --brand-800: oklch(0.38 0.1 250);
}

.button {
  background: var(--brand-700);
}

.button:hover {
  background: var(--brand-800);
}

.hero {
  background: linear-gradient(in oklch, oklch(0.6 0.16 260), oklch(0.75 0.16 70));
}
```

`oklch()` has worked in every major browser since 2023, so it needs no
fallback. The catch is gamut. A value the screen can't show gets mapped back
in, and its lightness can shift on the way, so check new colors at
[oklch.com](https://oklch.com/) before you ship them.

## Resources

- [OKLCH in CSS, why we moved from RGB and HSL](https://evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl): The case for OKLCH, with side by side palettes that make the HSL problem obvious.
- [OKLCH color picker](https://oklch.com/): Pick colors by lightness, chroma and hue, and see where the sRGB and P3 gamuts end.
- [oklch()](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/color_value/oklch): Syntax, ranges and browser support for the CSS function.
- [A perceptual color space for image processing](https://bottosson.github.io/posts/oklab/): Björn Ottosson's post that introduced Oklab, the space OKLCH is built on.
