Why oklch Changes Everything

If you've ever tried to create a color palette that looks good across light mode, dark mode, and every state in between, you've felt the pain of hex and HSL. Colors that look balanced in your picker appear wildly uneven on screen. And building derived colors — hover states, focus rings, disabled variants — becomes an exercise in manual guessing.

The Problem with HSL

HSL treats all hues as equal in perceived brightness, but human vision doesn't work that way. A pure yellow (#FFFF00) at 50% lightness is far brighter to the eye than a pure blue (#0000FF) at the same 50% lightness. This means you can't simply adjust the L channel and expect consistent results.

This is why every design system eventually ends up with hand-tweaked color scales — someone has to eyeball each shade because the math doesn't produce perceptually uniform steps.

The fundamental problem with HSL is that "lightness" doesn't mean what humans think it means. oklch fixes this by making lightness perceptually linear.

Enter oklch

oklch is a perceptually uniform color space designed for CSS. It has three channels:

  • L (Lightness) — 0 to 1, perceptually linear. Equal steps look equally different.
  • C (Chroma) — 0 to ~0.4, controls saturation intensity. 0 is gray.
  • H (Hue) — 0 to 360, the color wheel angle.

Because lightness is perceptually linear, you can mathematically generate color scales that actually feel consistent. No more hand-tweaking.

How Stride Uses It

Every color in Stride CSS is defined in oklch. This isn't just a cosmetic choice — it fundamentally changes how derived colors work:

color-mix() for derived states

Hover states, focus rings, and disabled variants all use color-mix(in oklch, ...). Because oklch mixing is perceptually uniform, a 20% lighter version of any color looks exactly 20% lighter — regardless of hue.

.btn:hover {
  background: color-mix(in oklch, var(--primary), white 15%);
}
.btn:active {
  background: color-mix(in oklch, var(--primary), black 10%);
}

@property animations

CSS @property lets you register custom properties with a defined syntax. This means you can animate individual oklch channels — hue shifts, lightness fades, chroma pulses — that are impossible with standard custom properties.

@property --hue {
  syntax: '<number>';
  inherits: false;
  initial-value: 60;
}
.element {
  background: oklch(0.7 0.15 var(--hue));
  transition: --hue 0.3s;
}
.element:hover { --hue: 280; }

The Result

With oklch as the foundation, Stride's entire color system is mathematically coherent. You don't need a preprocessor. You don't need a config file. You don't need to hand-tune 47 shades of blue. Just define your brand color in oklch and let the browser do the math.


Try Stride CSS

MIT licensed. Zero dependencies. oklch-native.

Explore Stride →

Get Early Access

Join the waitlist and be the first to try Gallop Builder.

No spam. Unsubscribe whenever.