OKLCH

A color space tuned to human perception — equal lightness (L) values look equally bright to the eye, no matter the hue.

Also known as: OK Lightness Chroma HuePerceptual color space
···
html
<div class="wrap">
  <div class="rowlabel">HSL <span class="muted">L 10→90%, 채도 고정</span></div>
  <div class="strip" id="hslStrip"></div>
  <div class="rowlabel">OKLCH <span class="muted">L 20→95%, 크로마 고정</span></div>
  <div class="strip" id="oklchStrip"></div>
</div>
css
.wrap{width:min(560px,94%);display:grid;gap:6px}
.rowlabel{font:700 clamp(10px,2.6vmin,12px)/1 ui-monospace,monospace;color:var(--fg);margin-top:10px}
.rowlabel .muted{color:var(--muted);font-weight:500}
.strip{display:grid;grid-template-columns:repeat(9,1fr);height:clamp(28px,7vmin,46px);border-radius:10px;overflow:hidden;border:1px solid var(--line)}
js
const STEPS = 9;
let hue = 20;
const hslStrip = document.getElementById('hslStrip'), oklchStrip = document.getElementById('oklchStrip');
for (let i = 0; i < STEPS; i++) { hslStrip.appendChild(document.createElement('div')); oklchStrip.appendChild(document.createElement('div')); }

function render() {
  for (let i = 0; i < STEPS; i++) {
    const t = i / (STEPS - 1);
    const l1 = 10 + t * 80;
    hslStrip.children[i].style.background = 'hsl(' + hue + ', 75%, ' + l1 + '%)';
    const l2 = (20 + t * 75) / 100;
    oklchStrip.children[i].style.background = 'oklch(' + l2.toFixed(2) + ' 0.15 ' + hue + ')';
  }
}
(function tick() {
  hue = (hue + 0.25) % 360;
  render();
  requestAnimationFrame(tick);
})();

HSL's lightness is just a mathematical average of sRGB values, so it drifts from actual perceived brightness — pure yellow already looks bright at L=50%, pure blue still looks dark at L=50%. OKLCH sidesteps this by expressing the perceptually-modeled OKLab space in cylindrical coordinates: L for lightness, C for chroma, H for hue.

In CSS it looks like oklch(62% 0.15 250). Sweep H while holding L constant and brightness stays far more even than the same experiment in HSL — which matters a lot when you want several palette colors to carry the same visual weight.

OKLCH can also reach beyond sRGB into wider gamuts like P3 on capable displays. Support is solid across modern browsers since 2023, but ship an HSL fallback if you still need to support older ones.

When to use

Use it for palettes or token systems that need a consistent brightness feel across many hues.