Modern CSS Colour: oklch(), color-mix() and Relative Colours

A
Author
07 Jul, 2026 1 min read 852 views

#hex and rgb() describe colours the way screens produce them, not the way people see them. Newer CSS colour functions make palettes more consistent and easier to generate.

oklch(): perceptual colour

:root {
  /* oklch(lightness chroma hue) */
  --brand-300: oklch(0.80 0.10 190);
  --brand-500: oklch(0.62 0.15 190);
  --brand-700: oklch(0.45 0.12 190);
}
  • Lightness (0-1) matches perceived brightness, so equal steps look like equal steps.
  • Chroma is colourfulness; hue is an angle from 0 to 360.
  • Keep lightness the same and change hue to get colours that feel equally bright, ideal for charts and status colours.
  • It can describe wide-gamut (P3) colours that hex can't.

color-mix(): tints, shades and transparency

.button:hover {
  background: color-mix(in oklch, var(--brand-500), black 15%);
}

.badge {
  background: color-mix(in srgb, var(--brand-500) 12%, transparent); /* soft tinted background */
}

Relative colour syntax

Take an existing colour and change one channel:

.card {
  --accent: oklch(0.62 0.15 190);
  border-color: oklch(from var(--accent) calc(l + 0.2) c h);   /* lighter */
  box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.3); /* 30% opacity */
}

Practical advice

  • Define a few base colours as variables and derive hover, focus and background shades from them.
  • Still check contrast for text; perceptual lightness helps but isn't a guarantee.
  • All of these work in current versions of every major browser.
Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.