Updated July 10, 2026

OKLCH & Modern CSS Color: The Practical Guide

OKLCH describes color with three perceptual values — Lightness, Chroma, Hue — where equal numbers mean equal appearance. That single property turns palette work from hand-correction into computation: even ramps, predictable contrast, dark themes derived instead of re-picked. This hub collects our guides on the color model and what it changes in practice; the one-image version is a ramp with genuinely even steps.

The problem it solves

Older models like HSL describe how RGB numbers combine, not how colors look. The result is familiar to anyone who has generated a palette: steps that bunch in the middle, hues that drift, one column of the palette passing contrast while its neighbor fails at the “same” lightness. When lightness means what it says, those problems stop being craft and become arithmetic.

OKLCH vs HSL demonstrates the lightness lie with concrete color pairs, and What Is Perceptual Uniformity? explains the property underneath: equal numeric distance means equal visible difference. What Is a JND adds the measurement that turns “these two look the same” into a testable claim.

What changes in practice

With a perceptual model underneath, a palette becomes a set of curves rather than a set of picks: a lightness curve places the steps, a chroma profile shapes where saturation peaks, and the same machinery derives dark themes and checks contrast. You rarely write oklch() values by hand — the model is the engine under the palette, and the values surface in generated tokens and in CSS when you need to reason about a color.

That engine role is how Scale Composer uses it: one scale drives color, typography and grid together, and the color side is computed in OKLCH so the ramps come out even without per-hue correction. The curve-based way of working has its own hub — color scales treats lightness curves and chroma profiles as design decisions in their own right — and the dark mode hub covers the derivation side: a dark theme computed by adjusting lightness and chroma rather than inverting anything.

Gamuts: the honest catch

Not every lightness-chroma-hue combination exists on a screen. Chroma has a ceiling that depends on lightness and hue, and wider-gamut P3 displays raise it. Good palette generation respects the ceiling with headroom instead of clipping against it — several guides below cover what that means for brand accents and imagery. sRGB vs Display-P3 maps the two gamuts and where wide-gamut screens actually are today, and Gamut Clipping shows what happens when a generated color exceeds the ceiling. Contrast is the other hard boundary a generated palette must respect; the contrast hub covers how to verify it.

Where to start reading

What Is OKLCH? is the ground-up introduction — start there if the three axes are new, then take What Is Chroma? for the one axis with no everyday-language equivalent. On the implementation side, The CSS oklch() Syntax covers writing the values, Converting Hex to OKLCH covers moving an existing palette in and out, and Browser Support for oklch() settles whether you can ship it without a build step (you can, natively, in all major browsers). Two guides then apply the model to problems that look unrelated until the model exposes them: Why Your Grays Aren’t Really Neutral on the residual chroma hiding in most gray scales, and Should Color Ramps Shift Hue? on when a hue drift is a bug and when it is a decision.

Guides in this hub

  • Browser Support for oklch() in 2026

    OKLCH browser support in 2026: every major engine has shipped oklch() since 2023. Who is still on the long tail, and the cheap fallbacks that cover them.

  • Color Spaces Explained for Designers

    Color spaces explained for designers: sRGB, P3 and Rec.2020 are gamuts, OKLCH and HSL are coordinate systems — and which combination fits which job.

  • Converting Hex to OKLCH (and Back)

    Converting hex to OKLCH is lossless; the way back can clamp. How the pipeline works, why the asymmetry exists, and a worked ramp from one real brand hex.

  • Gamut Clipping: Why Your Colors Get Crushed

    Gamut clipping crushes colors that exist in the model but not on screen: why channel clamping shifts hue, why ramps go flat, and how headroom prevents it.

  • OKLCH in Tailwind v4

    Tailwind OKLCH, in practice: v4 rebuilt its palette in OKLCH and moved config into CSS. How to define custom brand colors in @theme — and what that buys you.

  • OKLCH vs HSL: Why HSL Lies About Lightness

    OKLCH vs HSL: HSL's lightness is a fraction of RGB numbers, not a measure of perception — yellow and blue at 50% differ wildly. What OKLCH fixes, and how.

  • OKLCH vs LAB and LCH

    OKLCH vs LAB and LCH: what the 1976 and 2020 perceptual color spaces share, how OKLab fixed CIELAB's blue hue shift, and when each is the right tool.

  • Should Color Ramps Shift Hue?

    Color ramp hue shift, explained: why hand-tuned palettes rotated hue, why OKLCH makes constant hue look constant, and when rotation is a deliberate choice.

  • sRGB vs Display-P3: What Designers Need to Know

    sRGB vs Display-P3: what a gamut is, where P3's extra colors live, why hex can't express them, and when wide gamut is worth the effort in real projects.

  • The CSS oklch() Syntax Explained

    A practical reference for CSS oklch() syntax: the three values and alpha, worked button examples, relative colors with oklch(from …), and fallbacks.

  • What Is a JND — When Two Colors Look the Same

    The just noticeable difference color scientists measure: the smallest change an eye can reliably detect. Why palette steps within 0.02 OKLCH lightness merge.

  • What Is Chroma (and How Is It Not Saturation)?

    Chroma measures colorfulness absolutely; saturation is a percentage of whatever a hue allows. Why the difference matters for palettes and accent colors.

  • What Is OKLCH? A Designer's Explanation

    OKLCH describes color with three values that match human perception: lightness, chroma, hue. Learn why it replaced HSL for palettes, ramps and contrast.

  • What Is Perceptual Uniformity?

    Perceptual uniformity means equal numeric distances look like equal visible differences. Why RGB and HSL fail the test, and what uniformity buys design work.

  • Why Your Grays Aren't Really Neutral

    A neutral gray color with equal RGB channels often reads cold next to a brand palette. Why perception shifts grays, and how a whisper of chroma fixes it.

Start from your own color

The model makes the most sense with a color you care about: drop a brand color into Scale Composer and it suggests supporting colors derived from it — then watch the ramps it builds hold their lightness steps across every hue. That behavior is OKLCH, seen rather than explained.

Frequently asked questions

What is OKLCH in simple terms?

A way to describe color with three values that match human perception — Lightness (how bright it looks), Chroma (how colorful it is), and Hue (which color it is). Two colors with the same L genuinely look equally light.

Why is OKLCH better than HSL?

HSL's lightness is computed from RGB numbers, not perception — 50% yellow looks near-white while 50% blue looks dark. In OKLCH, equal lightness looks equal, which makes generated palettes and contrast predictable.

Is oklch() supported in browsers?

Yes — it has been native CSS in all major browsers since 2023, with no build step required. Fallbacks only matter for legacy traffic.

What is chroma?

The amount of colorfulness, measured absolutely — 0.15 chroma is the same "amount of color" in any hue. That's different from saturation, which is a percentage of whatever a given hue and lightness happen to allow.

Does Tailwind use OKLCH?

Tailwind v4's default palette is defined in OKLCH, and modern palette tooling broadly has moved the same way — generated ramps come out even without per-hue hand-correction.

Can hex codes store P3 colors?

No. Hex is limited to sRGB; wide-gamut colors need the color(display-p3 …) syntax or a wide-gamut-capable space like OKLCH. Displays on most current phones and Macs can show P3.