The problem with HSL colors

The problem with HSL colors

Introduction

HSL has been standard for some time. OKLCH is a newer color space that's becoming popular.

I want to explore the issues with HSL and explain why OKLCH is better.

HSL

Perceptual Uniformity Problem

/* These HSL colors have equal lightness steps */
.color1 {
  color: hsl(250, 100%, 20%);
}

.color2 {
  color: hsl(250, 100%, 40%);
}

.color3 {
  color: hsl(250, 100%, 60%);
}

But to your eye, the jump from 20% to 40% might look much bigger than 40% to 60%. HSL says they're equal steps, but your brain eyes disagrees.

The Yellow Problem

/* These have the same lightness in HSL */
.yellow {
  color: hsl(60, 100%, 50%);
} /* Yellow */

.blue {
  color: hsl(240, 100%, 50%);
} /* Blue */

The yellow appears much brighter than the blue, even though HSL says they have the same lightness. This is because our eyes are more sensitive to yellow.

Animation Problem

When you animate between colors in HSL:

.button {
  background: hsl(0, 100%, 50%); /* Red */
  transition: background 1s;
}

.button:hover {
  background: hsl(240, 100%, 50%); /* Blue */
}

The transition might show unexpected dull colors because HSL changes colors in equal mathematical steps, not in steps that look equal to our eyes.

These problems exist because HSL was designed for computers to process colors easily, not for how humans actually see color.

OKLCH solves these issues by aligning with how our eyes see color differences, making transitions smoother and color relationships feel more natural.

OKLCH

Basic Structure: oklch(65% 0.3 250)

  • First number (65%): Lightness

  • Second number (0.3): Chroma (colorfulness)

  • Third number (250): Hue (color angle)

Lightness (L)

  • Range: 0-100%

  • 0% = Black

  • 100% = White

  • Perceptually uniform (50% looks like true middle gray to human eyes)

Chroma (C)

  • How colorful/saturated

  • Range: 0 to about 0.4

  • 0 = Gray

  • Higher = More vivid

  • Maximum depends on the color and display capabilities

Hue (H)

  • Color angle like HSL

  • 0-360 degrees

  • Examples:

    • 0 = Red

    • 90 = Yellow

    • 180 = Green

    • 270 = Blue

The "OK" Part

  • Based on OKLAB color space

  • "OK" = Optimized Kánczos (named after researchers)

  • Designed around human perception studies

  • Mathematically optimized for how we see color

Practical Usage

.button {
  /* A vivid blue */
  color: oklch(65% 0.3 250);

  /* A pastel red */
  color: oklch(80% 0.1 25);

  /* A deep purple */
  color: oklch(40% 0.2 300);
}

The key is that each change in these numbers matches how we actually see color changes with our eyes, not just how computers handle them.


You can also customize the opacity:

/* Two equivalent ways to write it: */
color: oklch(65% 0.3 250 / 0.5); /* With slash */
color: oklch(65% 0.3 250 / 50%); /* Can also use percentage */

/* You can also use the longer form: */
color: oklcha(65% 0.3 250 0.5); /* 'a' suffix like hsla */