Designing with OKLCH in modern CSS
Design · 5 min read
OKLCH has moved from a colour-science curiosity to a genuinely useful tool in everyday CSS. It solves a specific, practical problem: making colour adjustments behave the way you expect, rather than the way the maths happens to work out.
What the three OKLCH channels actually mean
OKLCH stands for lightness, chroma and hue. Lightness runs from 0, black, to 1, white, and is calibrated to match perceived brightness rather than a raw numeric average of colour channels. Chroma measures how vivid or muted a colour is, starting at 0 for grey and increasing with intensity. Hue is an angle in degrees, just like in HSL, running from red through yellow, green, blue and back to red.
Because these three channels are genuinely independent of each other in how they affect perception, changing one rarely produces the surprising side effects you sometimes get in HSL, where increasing saturation can make a colour look subtly different in brightness too.
Writing an OKLCH colour in CSS
The syntax looks like oklch(60% 0.15 250), where the first number is lightness as a percentage, the second is chroma as a decimal, and the third is hue in degrees. You can add transparency with a slash, such as oklch(60% 0.15 250 / 0.5) for fifty percent opacity.
It is worth pasting a few example colours into a colour converter first, just to get a feel for typical chroma ranges. Chroma above roughly 0.3 quickly runs outside what standard screens can display for many hues, so very high numbers often get silently clipped to the nearest displayable colour.
Building an evenly spaced palette
The clearest advantage of OKLCH shows up when generating a scale of shades from one base colour. Keep hue and chroma fixed, and step the lightness value evenly, say from 95% down to 15% in increments of 10, and you get a tint and shade scale that looks genuinely evenly spaced to the eye.
Try the same trick in HSL and the middle of the scale often looks disproportionately bright or dark depending on the hue, because HSL's lightness does not track perceived brightness. OKLCH's whole reason for existing is to fix exactly this kind of inconsistency.
Smoother gradients with OKLCH interpolation
CSS gradients can now interpolate directly in the OKLCH colour space by adding 'in oklch' to a linear-gradient or similar function. This avoids the muddy, greyish-looking midpoints that often appear when a gradient is interpolated in plain RGB, especially between colours that sit far apart on the hue wheel.
This matters most for gradients that span a wide hue range, such as a rainbow-style progress indicator or a data visualisation scale, where RGB interpolation tends to dip through unattractive brownish or grey tones partway through.
Relative colour syntax for quick variants
Modern CSS lets you derive a new colour from an existing one without a preprocessor, using relative colour syntax such as oklch(from var(--brand) calc(l - 0.1) c h) to produce a version ten percentage points darker. This keeps a single source colour as the true source of truth, with variants generated live in the stylesheet.
This is particularly useful for hover and active states, where you want a colour that is reliably a bit darker or a bit more saturated than a base colour, without hand-picking and maintaining a separate value for every state.
Wide gamut colours and modern screens
Many current phones, tablets and monitors can display colours outside the older sRGB gamut that HEX and RGB are built around. OKLCH can describe those more vivid colours directly, which means designs built with it can look noticeably richer on capable hardware, while still degrading gracefully on older screens.
You do not need to do anything special to benefit from this: simply choosing OKLCH values with chroma near the edge of what is displayable will render more vividly on wide-gamut hardware and fall back sensibly elsewhere.
Fallbacks for older browsers
If your audience includes older browsers that do not understand OKLCH, provide a HEX or RGB declaration first, followed by the OKLCH declaration. Browsers apply the last value they understand, so unsupported browsers use the fallback while modern ones use OKLCH automatically.
A colour converter is the quickest way to generate that fallback value, since you can paste your OKLCH colour in and read off an accurate HEX equivalent rather than guessing.
Common mistakes when starting with OKLCH
The most common early mistake is picking chroma values that are too high for the intended lightness and hue, resulting in a colour that gets clipped and looks different from what was intended. If a colour looks unexpectedly dull compared with what you typed, try lowering the lightness slightly or reducing chroma.
Another common mistake is assuming OKLCH hue angles line up exactly with HSL hue angles for the same-looking colour. They are close for many hues but not identical, so always verify a converted colour visually rather than assuming the numbers transfer directly.
A practical starting workflow
Pick a base brand colour, convert it to OKLCH using a colour converter, then generate a tint and shade scale by adjusting lightness alone. Use relative colour syntax for interactive states. Add gradient interpolation in OKLCH wherever a gradient spans more than a small hue range. This covers the majority of practical uses without needing deep colour-science knowledge.
Common questions
- Do I need a preprocessor to use OKLCH?
- No. OKLCH, gradient interpolation in OKLCH, and relative colour syntax are all supported natively in modern CSS in current major browsers, without any build step or preprocessor. A preprocessor can still be convenient for generating fallback values in bulk, but it is not required.
- Why do my OKLCH colours look different from what I expected?
- This usually means the chroma value you chose is outside the range that is actually displayable at that lightness and hue, so the browser clips it to the closest colour it can show. Lower the chroma slightly, or check the value in a colour converter to see a preview before using it.
- Is OKLCH only useful for gradients?
- No, gradients are just the most visually obvious benefit. OKLCH is equally useful for building tint and shade scales, defining consistent hover and focus states with relative colour syntax, and generally making colour edits behave predictably during day-to-day design work.
- How do I provide a fallback for browsers that do not support OKLCH?
- Declare a HEX or RGB colour first, then declare the OKLCH version immediately after on the same property. Browsers that do not understand OKLCH will ignore that line and keep the earlier fallback, while browsers that support it will use the OKLCH value.
- Does OKLCH replace HEX entirely?
- Not necessarily. HEX remains a fine, compact way to store a finished colour, especially for external documentation or older tooling. OKLCH is more useful during the active design and adjustment phase, and the two can comfortably coexist within the same project.