OKLCH and OKLab in 2026: why modern CSS colour replaces your RGB

Since early 2026 Chrome 111+, Edge 111+, Firefox 113+ and Safari 15.4+ all support oklch(), oklab() and color-mix() — covering over 95 % of browsers worldwide. What was an experimental feature behind browser flags two years ago is now production-ready. I have switched three projects to OKLCH in the past few months, and the result is striking: more uniform colour scales, predictable mixing, noticeably prettier gradients. What OKLCH technically is, why it beats RGB and HSL — and how to migrate your existing design system.

Why RGB and HSL have always been bad colour models

RGB is a hardware model: red, green, blue, each 0-255. It matches how screens work but has little to do with human perception. #ff0000 (pure red) and #0000ff (pure blue) are RGB-symmetric, but they appear completely different in brightness. That's not just aesthetically ugly — it breaks any automatic brightness sorting.

HSL came in CSS3 with the promise to fix this: Hue, Saturation, Lightness. Sounds human-friendly. Sadly also wrong. hsl(60, 100%, 50%) is yellow at '50 % lightness', hsl(240, 100%, 50%) is blue at '50 % lightness' — but the yellow looks dramatically brighter than the blue. HSL computes 'lightness' geometrically in the RGB cube, not perceptually. Anyone building a palette with HSL gets banding, uneven contrasts and surprising mix results.

Concrete example from an old project: in 2022 I built a day/night palette with HSL. At hsl(200, 80%, L) with L from 10 % to 90 % in 10-step increments I expected an evenly stepped brightness ramp. What I got: two very dark steps, then an abrupt jump into a punchy mid range, then a few near-identical bright steps at the end. The consequence: UI designs in which 'gray-50' and 'gray-100' are barely distinguishable, but 'gray-300' and 'gray-400' look like different colours.

What OKLCH does better

OKLCH stands for 'Oklab Lightness, Chroma, Hue'. It is a cylindrical variant of the Oklab colour space designed by Björn Ottosson in 2020. The decisive point: Oklab is perceptually uniform. A distance in this colour space roughly matches what the human eye experiences as 'this far apart'. Building a palette from L=0.1 to L=0.9 in OKLCH gives you an evenly stepped brightness ramp — across all hue values.

Three axes: L (Lightness, 0 to 1, sometimes written as 0–100 %). Perceptually correct brightness. C (Chroma, 0 to ~0.4). How 'saturated' the colour is; 0 = grey, higher = punchier. H (Hue, 0 to 360 degrees). Which colour — 0 = red, 120 = green, 240 = blue (similar conventions to HSL but with perceptually better transitions).

Example: oklch(0.7 0.15 250) gives you a lighter blue with moderate saturation. Switch to oklch(0.7 0.15 50) and you get a lighter orange with the same perceived brightness and saturation — you only swap the hue. In HSL, the same swap yields a markedly brighter orange than the blue. OKLCH turns palette building into pure number work instead of visual trial and error.

color-mix() — finally a sensible way to mix colours

color-mix() is the second killer feature of 2026: blend two colours in a chosen colour space at a percentage. color-mix(in oklch, var(--brand) 60%, white) gives you a 60 %-brand-40 %-white mix, computed in the perceptually uniform space. In RGB such mixes look muddy — 'brownish grey' instead of 'lighter brand'. In OKLCH the hue stays stable and the blend looks natural.

Practical use in a design system: instead of manually maintaining each variant of a brand colour as an HSL constant, define the brand colour once and derive hover/active states via color-mix(). --brand: oklch(0.6 0.2 250); --brand-hover: color-mix(in oklch, var(--brand), white 15%); --brand-active: color-mix(in oklch, var(--brand), black 10%);. DRY, robust against brand refactors, and works in every modern browser.

An additional advantage: dark modes get easier. Instead of defining a separate dark-mode variable for every shadow, set the dark-mode background to a darker OKLCH and compute all component colours via color-mix() relative to it. The entire theme switch fits in 3–5 instead of 30–50 CSS variables. A dream in 2024, the standard in 2026.

Migrating an existing Tailwind palette

Tailwind CSS started rebuilding its default palette on OKLCH internally in 2024. Anyone on Tailwind 4.x has an OKLCH palette under the hood — even if they still write bg-blue-500. Anyone maintaining a custom palette (typically for brand colours) benefits from migrating it to OKLCH.

Migration step: take the existing hex codes of your brand colours and feed them into an OKLCH converter (online tools available, or our own Color Converter). Place the lightness on a 0.1 to 0.9 scale, tune chroma so the brand identity stays recognisable. Nine tone steps yield a perceptually uniform scale: --brand-50: oklch(0.95 0.05 H); down to --brand-900: oklch(0.2 0.18 H);, with constant hue H.

What you will likely discover: your old HSL ramp has two steps that are nearly identical somewhere, and another step that feels like a jump. Not your fault — that's HSL. After OKLCH migration the spacing is even, the eye reads the ramp intuitively. For me a 9-step brand ramp took about 45 minutes; the result measurably improved WCAG contrast tests.

Gradient renaissance: prettier blends without the 'grey belly'

A classic CSS problem: linear-gradient(to right, blue, yellow) doesn't look like a blue-to-yellow transition in the browser, but like blue → dirty green/grey → yellow. The reason is the RGB model again: between blue and yellow lies a grey value through which the gradient interpolates.

With the 2024 CSS Color 4 update you can explicitly state the interpolation colour space: linear-gradient(in oklch to right, blue, yellow) produces a transition that traverses the full colour circle cleanly — the middle now looks like a light turquoise/green, not grey. Anyone designing a logo, hero banner, or UI accent with a gradient suddenly has a much better tool. Our CSS Gradient Generator supports this mode in its latest version.

If you want it even finer: color-mix() can be nested inside gradients. Three-stop gradients with defined intermediate mix points enable very fine visual tuning. A mesh gradient (multiple overlapping radial gradients) looks silky in OKLCH interpolation — the old RGB method by comparison feels jagged and dirty. For UI design this is a clear step up.

Practical steps for your next branch

A concrete list I work through in my own 2026 projects:

  • Check browser support. caniuse.com/oklch and caniuse.com/color-mix — both green from 2026 for > 95 % of users. If you still need to support Safari 14, fallback with @supports.
  • Migrate one brand ramp. Best results: 9-step ramp with constant hue and linearly interpolated L from 0.1 to 0.9. Keep chroma medium (0.1 to 0.15) for muted UI colours.
  • Adopt color-mix() for hover/active. Saves 50 % of the custom properties in your theme.
  • Re-evaluate gradients. Every linear or radial gradient should explicitly set the interpolation mode, minimum in oklch.
  • Verify WCAG contrast. OKLCH gives more predictable contrast outcomes — but you still verify. Tools like our Contrast Checker do it in 10 seconds.

If you still doubt that it works properly in real browsers: spend an afternoon on a spike in a test branch. You will see the results look more consistent and prettier on whatever device you have at hand (Mac, iPhone, Android, Windows).

What's next in CSS Color

On the CSS Working Group's table in 2026: relative color syntax (color: oklch(from var(--brand) 0.9 c h) — same brand hue but a forced lightness), HDR colours for high-dynamic-range displays (Display-P3, Rec.2020), and finally mesh gradients as a native CSS standard (instead of manually built from multiple radial gradients). First implementations likely come early 2027.

My takeaway for 2026: OKLCH is no longer an experimental feature, it is best practice. Anyone starting a new project should work in OKLCH and color-mix() from day one — all modern frameworks (Tailwind, MUI, Mantine, Radix) are compatible or use it internally. The HSL era is over; it served its purpose for 15 years, but we have something better now.

Frequently asked questions

Do I have to replace all my old hex codes?

No. #ff0000 and rgb(255, 0, 0) still work. OKLCH is an additional notation, not a replacement. Migration makes sense where you work systematically (brand ramps, theme variables, gradients). One-off look-ups like 'red X icon' can pragmatically stay hex.

What's the difference between OKLab and OKLCH?

OKLab is the base colour space: three axes L (lightness), a (green-red), b (blue-yellow). OKLCH is a cylindrical reparameterisation: L (same), C (chroma — distance from the grey axis), H (hue — angle in the colour wheel). For UI design OKLCH is usually more practical because 'hue' is more intuitive than 'a/b' coordinates. Both are available in CSS.

How do I handle gamut issues?

OKLCH can describe values that sRGB (the standard screen profile) cannot represent. In that case the browser performs 'gamut mapping' — clipping the colour to the nearest displayable value. For most UI colours (medium chroma) this is rare. If you need highly saturated colours (chroma > 0.2), check in the browser devtools colour picker that the desired value reaches the renderer.

Does OKLCH also work in HTML emails?

Mostly no. Email clients (Outlook, Gmail web, Apple Mail) barely support OKLCH yet, and Outlook on Windows with the Word rendering engine destroys any modern CSS regardless. For email templates hex/RGB stays the only safe choice. Only when embedding web components in an inbox can you benefit from OKLCH — even then only partly.

Where can I learn OKLCH better?

Three sources that helped me: Björn Ottosson's original Oklab article (bottosson.github.io), Evil Martians' Chronicles article 'OKLCH in CSS', and the oklch.com tool for interactive exploration. Plus: implement one project — that beats any theory.

Is the switch worth it for very small projects?

For a single landing page with 3 colours: honestly no, hex is fine. As soon as you have a brand ramp, gradient backgrounds, dark mode, or hover states, yes. Investment is 30–60 minutes of learning curve, which then makes every further project faster and cleaner. My rule of thumb: from 5 connected colours on, OKLCH pays off.

Note: This article is a hands-on report from my own projects, not an official W3C standard excerpt. Browser versions and support figures are based on caniuse.com data from June 2026 and can update daily.

Comments