Deft
Ask AI

Search

Search skills, authors and topics

jakubkrehel / oklch-skill

oklch-skill

Practical OKLCH color workflow skill for building consistent, accessible, and tunable color systems in modern UIs.

Install

npx skills add https://github.com/jakubkrehel/oklch-skill --skill oklch-skill

Gamut Awareness & Tailwind v4

sRGB vs Display P3

Every sRGB color exists within Display P3, but not every P3 color exists within sRGB. Display P3 covers ~50% more colors.

Max chroma varies by lightness and hue

The gamut boundary is irregular. At L=0.5 in sRGB:

  • Highest chroma: purple (H ≈ 285) at C ≈ 0.29
  • Red-orange (H ≈ 0-30): C ≈ 0.20
  • Lowest chroma: cyan (H ≈ 195) at C ≈ 0.09

The peak hue shifts with lightness. At L=0.7 magenta peaks, at L=0.9 green peaks. Cyan consistently has the lowest max chroma.

Gamut checking

If a color's chroma exceeds the maximum for its L/H/space, it clips. The fix: reduce chroma while keeping L and H constant.

css
/* Out of sRGB gamut */oklch(0.7 0.35 150)
/* Clamped to max chroma */oklch(0.7 0.22 150)

CSS fallback patterns

css
/* sRGB fallback for all browsers */.accent {  color: oklch(0.7 0.2 150);}
/* P3 enhancement for wider gamut displays */@media (color-gamut: p3) {  .accent {    color: oklch(0.7 0.3 150);  }}

For browsers without oklch support:

css
.accent {  color: #4ade80;}
@supports (color: oklch(0 0 0)) {  .accent {    color: oklch(0.7 0.2 150);  }
  @media (color-gamut: p3) {    .accent {      color: oklch(0.7 0.3 150);    }  }}

Tailwind v4

Tailwind CSS v4 defines its default palette in oklch. Custom themes should follow the same convention.

Custom color scale with @theme

css
@theme {  --color-brand-50: oklch(0.971 0.012 250);  --color-brand-100: oklch(0.932 0.028 250);  --color-brand-200: oklch(0.882 0.048 250);  --color-brand-300: oklch(0.812 0.078 250);  --color-brand-400: oklch(0.722 0.148 250);  --color-brand-500: oklch(0.623 0.188 250);  --color-brand-600: oklch(0.535 0.168 250);  --color-brand-700: oklch(0.445 0.138 250);  --color-brand-800: oklch(0.362 0.108 250);  --color-brand-900: oklch(0.289 0.078 250);  --color-brand-950: oklch(0.215 0.048 250);}

This gives you bg-brand-500, text-brand-200, etc. automatically.

Opacity modifiers

Tailwind's opacity modifier syntax works with oklch:

html
<div class="bg-brand-500/50"></div><!-- Compiles to: oklch(0.623 0.188 250 / 0.5) -->

Migrating existing themes

  1. Convert all hex values in @theme to oklch
  2. Replace any theme() references that used hex
  3. Test dark mode — oklch values may look slightly different due to perceptual accuracy
  4. Check for hardcoded hex in component code and convert those too