1. The short answer
You probably want all three, used for different things:
| Format | Use for | Avoid for |
|---|---|---|
| HEX | Storage, handoff, tool interchange | Doing color math by hand |
| HSL | Tweaking a single color in code | Building scales, predicting contrast |
| OKLCH | Building scales, gradients, dark mode, contrast tuning | Older-browser-only stylesheets |
2. HEX: the universal default
Hexadecimal color notation (#1c749f) is a compact encoding of three 8-bit channels (red, green, blue) in the sRGB color space. It's the lowest common denominator of web color — supported since CSS1 (1996), universal across every design tool, and trivially parseable.
What HEX is good at: being a transport format. If you need to write a color down, paste it in Slack, send it to a contractor, or store it in a database, HEX is the right answer. Every conversion target speaks HEX.
What HEX is bad at:doing anything operational with the color. The channels don't correspond to anything meaningful — you can't tell if #a1b2c3 is light or dark, what hue it is, or how it compares to #b3c4d5 without converting first. HEX is a destination, not a workshop.
HEX also doesn't natively encode opacity or wide-gamut color. The 8-digit variant #1c749fffadds alpha, but most tools don't round-trip it cleanly, and colors outside sRGB can't be expressed at all.
3. HSL: intuitive, but mathematically broken
HSL — hue, saturation, lightness — was standardized as a CSS color function in CSS Color Module Level 3 (W3C Recommendation, June 2011) and quickly became the “readable” alternative to HEX. The appeal is obvious: hsl(212, 70%, 37%) tells you the color is a saturated blue at a moderate lightness. A designer can read that.
The problem is that HSL is a simple geometric transform of sRGB — it inherits sRGB's lack of perceptual uniformity. In HSL:
- Lightness isn't perceived lightness. HSL yellow at L=50% looks near-white. HSL blue at L=50% looks mid-tone. The same lightness number doesn't produce equally light colors.
- Saturation isn't perceived saturation. HSL red at S=100% feels much more saturated than HSL teal at S=100%, even though the number is the same.
- Interpolation goes through ugly mid-tones. Interpolating between two HSL colors often produces a grey, brown, or muddy crossover in the middle because the math passes through the gamut center.
HSL is fine for one-off operations on a single color — nudging saturation up, shifting hue by 20°, lightening a specific shade. It's a poor foundation for systematic color work, which is why every modern design-system tool has moved off it.
4. OKLCH: perceptually uniform
OKLab, created by Björn Ottosson in 2020, is a modern perceptual color space designed to fix the problems with older perceptual spaces like CIELAB while staying simple to compute. OKLCH is its polar form: lightness, chroma (saturation-like), and hue angle.
A typical OKLCH color looks like:
oklch(45% 0.12 245)
— read as “45% lightness, 0.12 chroma, 245° hue”. Chroma in OKLCH runs from 0 (grey) up to roughly 0.4 for the most saturated sRGB colors; the practical upper bound depends on hue and lightness because the sRGB gamut has weird shapes in perceptual space.
Why OKLCH matters for design systems:
- Same L = same perceived lightness across hues. Yellow at L=60% and blue at L=60% look equally bright. That makes it possible to build scales where step 600 (say) has a consistent perceived darkness across your entire palette.
- Interpolation looks good. Gradients and mid-step generation pass through colors that look intermediate, not muddy.
- Hue stays constant when you change lightness. Adjusting L without touching H doesn't drift the color toward a different hue — a common failure mode in HSL and raw sRGB.
- Gamut is explicit. Colors outside sRGB just have chroma values higher than sRGB can render. You can detect and gamut-map predictably, which matters as P3 displays become standard.
Browser support: The CSS oklch() function is part of CSS Color Module Level 4. It shipped in Safari 15.4 (March 2022), Chrome 111 (March 2023), and Firefox 113 (May 2023). For modern-browser-only sites, it's safe to use natively. For broader support, generate OKLCH at design time and serialize to HEX or sRGB for the stylesheet.
Tooling has caught up. Tailwind CSS v4 (early 2025) replaced its entire default palette with OKLCH values. Radix Colors, Open Props, and most contemporary color tools now work in OKLCH or OKLab natively.
5. OKLab, LAB, and other formats
A few formats you'll encounter that live in the same neighborhood:
- OKLab — the Cartesian form of the same color space as OKLCH. Components are L (lightness), a (green↔red axis), b (blue↔yellow axis). Better for linear math (averaging two colors, computing distances); OKLCH is better for design controls.
- CIELAB / lab() — the older perceptual color space from the CIE. It mostly works but has known problems with blue and purple. OKLab was designed to fix these specifically.
- LCH / lch() — the polar form of CIELAB, same relationship as OKLCH is to OKLab. Same caveats apply.
- color(display-p3 ...) — not a color space per se, but a way to encode colors in the wider P3 display gamut. Useful for vibrant brand colors that go beyond sRGB, especially on Apple hardware.
- HSV / HSB — close cousin of HSL with the same perceptual problems. Used in some design tools (notably Photoshop). Treat like HSL.
6. When to use which
A practical decision tree:
- Writing a color down in design specs, tickets, or docs? HEX. It's the format every reader can paste anywhere.
- Designing a single state and want to tweak it by hand? HSL is fine — nudging hue and lightness sliders on one color is exactly its strength.
- Generating a scale, ramp, or sequence of related colors? OKLCH. The reason your hand-tuned scales feel inconsistent across hues is HSL — switching to OKLCH usually fixes it.
- Animating or interpolating between two colors? OKLCH (or OKLab). The midpoint will look intermediate, not muddy.
- Generating dark-mode variants? OKLCH. Inverting lightness while holding hue and chroma gives you a coherent dark theme; doing the same in HSL or sRGB drifts hues unpredictably.
- Tuning for accessible contrast? Pair OKLCH with APCA (see our APCA vs WCAG guide). Adjusting OKLCH lightness alone usually lands you in the right contrast range across hues.
7. How Palette Daddy handles formats
Palette Daddy accepts HEX, OKLCH, or HSL as input. Internally, the generator works in a perceptual color space so that lightness, chroma, and hue can be manipulated independently when producing the 11-step scale (see our 11-step color scale guide for why that matters).
Outputs are shown in your preferred format (HEX by default; toggle to OKLCH or HSL in the input panel). The Token Studio JSON export serializes to HEX for maximum compatibility with downstream tools — pick OKLCH on the input side, get clean HEX out the other end.
8. Frequently asked questions
9. Further reading
- Björn Ottosson — A perceptual color space for image processing — the original OKLab paper. The math, the motivation, the comparisons against CIELAB.
- CSS Color Module Level 4 — the W3C spec where oklch(), lab(), color(), and friends are defined.
- OKLCH color picker — Evil Martians' interactive picker. Best way to build intuition for what L, C, and H actually do.
- Tailwind CSS v4 — the v4 release post, which discusses moving the default palette to OKLCH and why.
- Building an 11-step color scale (our guide) — the practical side: how the formats here translate into a working design system scale.
