OKLAB Cartesian Coordinate System
OKLAB is a Cartesian coordinate system for color representation, fundamentally different from the polar coordinate system used by OKLCH. While OKLCH uses Lightness (L), Chroma (C), and Hue (H) in a cylindrical arrangement, OKLAB uses three perpendicular axes.Copy
OKLAB CARTESIAN COORDINATE SYSTEM
------------------------------------------------------------------------
+b (Yellow)
|
|
|
| * (L, a, b)
| /
| /
| /
-a -----------------+----------------- +a
(Green) | \ (Red/Magenta)
| \
| \
| * Second Color
|
-b (Blue)
L axis: Perpendicular to this plane (0 = black, 1 = white)
a axis: Green (-) to Red/Magenta (+)
b axis: Blue (-) to Yellow (+)
KEY PROPERTY: Straight line between two colors = perceptually uniform path
Mathematical Relationship: OKLAB to OKLCH
The conversion between OKLAB (Cartesian) and OKLCH (Polar) follows standard coordinate transformation equations:Copy
┌───────────────────────────────────────────────────────────────────────┐
│ COORDINATE CONVERSION FORMULAS │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ OKLAB (Cartesian) → OKLCH (Polar): │
│ ────────────────────────────────── │
│ C = √(a² + b²) // Chroma = distance from center │
│ H = atan2(b, a) × 180/π // Hue = angle in a,b plane │
│ if H < 0: H += 360 // Normalize to [0, 360) │
│ │
│ OKLCH (Polar) → OKLAB (Cartesian): │
│ ────────────────────────────────── │
│ a = C × cos(H × π/180) // a-axis projection │
│ b = C × sin(H × π/180) // b-axis projection │
│ │
└───────────────────────────────────────────────────────────────────────┘
Copy
// Cartesian to Polar conversion
// Chroma = distance from center (magnitude of a,b vector)
const c = Math.sqrt(a * a + b * b);
// Hue = angle in a,b plane (converted to degrees)
let h = (Math.atan2(b, a) * 180) / Math.PI;
if (h < 0) h += 360;
Copy
// Polar to Cartesian conversion
// a = C * cos(H)
const a = oklch.c * Math.cos((oklch.h * Math.PI) / 180);
// b = C * sin(H)
const b = oklch.c * Math.sin((oklch.h * Math.PI) / 180);
Coordinate System Comparison
Copy
COORDINATE SYSTEM COMPARISON: OKLCH vs OKLAB
--------------------------------------------------------------------
OKLCH (Polar/Cylindrical) OKLAB (Cartesian/Rectangular)
========================= =============================
L (Lightness) L (Lightness)
| |
| H (Hue) | +b
| / \ | |
| / \ | |
| / \ -a --+---+---+a
| \ | |
+----------\ | -b
| C \ |
| (radius) \
Intuitive for: Optimal for:
- Human color selection - Linear interpolation
- Hue rotation - Color mixing
- Identity definition - Transparency blending
- Golden angle distribution - Gradient generation
CSS: oklch(L% C H) CSS: oklab(L% a b)
Example: oklch(55% 0.15 230) Example: oklab(55% -0.12 -0.09)
The color-mix() Function
Thecolor-mix() function was introduced in CSS Color Level 5 to enable programmatic color blending directly in CSS.
Copy
color-mix(in <color-space>, <color1> [<percentage>], <color2> [<percentage>])
<color-space>: The interpolation color space (srgb, lab, oklab, oklch, etc.)<color1>,<color2>: The colors to blend<percentage>: Optional weighting (default 50% each)
Why OKLAB for color-mix()?
Copy
/* Using color-mix() for perceptually accurate transparency (in oklab color space) */
/* Light overlays (using color-mix in oklab) */
--color-overlay-light-1: color-mix(in oklab, var(--color-text-primary), transparent 92%);
--color-overlay-light-2: color-mix(in oklab, var(--color-text-primary), transparent 88%);
--color-overlay-light-3: color-mix(in oklab, var(--color-text-primary), transparent 84%);
--color-overlay-light-4: color-mix(in oklab, var(--color-text-primary), transparent 80%);
/* Dark overlays (using color-mix in oklab) */
--color-overlay-dark-1: color-mix(in oklab, black, transparent 95%);
--color-overlay-dark-2: color-mix(in oklab, black, transparent 90%);
--color-overlay-dark-3: color-mix(in oklab, black, transparent 80%);
--color-overlay-dark-4: color-mix(in oklab, black, transparent 70%);
Interpolation Behavior: OKLAB vs sRGB
Copy
INTERPOLATION PATH COMPARISON
--------------------------------------------------------------------
Example: Mixing Blue (oklch 55% 0.15 230) with Orange (oklch 55% 0.15 50)
+------------------------------------------------------------------+
| sRGB Interpolation |
| (NON-perceptually uniform) |
| |
| Blue ---------> MUDDY <-------- Orange |
| #2380c7 BROWN #b58900 |
| #7d7064 |
| |
| Path curves through low-saturation zone = "muddy" appearance |
+------------------------------------------------------------------+
+------------------------------------------------------------------+
| OKLAB Interpolation |
| (Perceptually uniform) |
| |
| Blue ---------> CLEAN <-------- Orange |
| #2380c7 PURPLE #b58900 |
| #8b6aa0 |
| |
| Straight line through color space = maintains saturation |
+------------------------------------------------------------------+
KEY INSIGHT: OKLAB's straight-line interpolation preserves perceived
chroma throughout the transition, preventing "muddy" intermediate colors.
color-mix() Pattern Taxonomy
Copy
COLOR-MIX() PATTERN TAXONOMY
--------------------------------------------------------------------
PATTERN A: Transparency Derivation
===================================
color-mix(in oklab, <CORE-COLOR>, transparent <N%>)
Purpose: Create semi-transparent versions of Core Colors
Usage: Backgrounds, selections, overlays
-------------------------------------------------------------------
PATTERN B: Lightness Adjustment
================================
color-mix(in oklch, <CORE-COLOR>, white <N%>)
color-mix(in oklab, <CORE-COLOR>, black <N%>)
Purpose: Create lighter/darker variants of Core Colors
Usage: Hover states, active states, shadows
-------------------------------------------------------------------
PATTERN C: Saturation Reduction
================================
color-mix(in oklab, <CORE-COLOR>, gray <N%>)
Purpose: Desaturate colors (reduce chroma)
Usage: Disabled states, muted variants, comments
-------------------------------------------------------------------
PATTERN D: Color Blending
==========================
color-mix(in oklab, <CORE-COLOR-A>, <CORE-COLOR-B> <N%>)
Purpose: Blend two Core Colors together
Usage: Merge lines, gradients, state transitions
Implementation Examples
Copy
/* Derived colors using color-mix() */
--oklch-primary-hover: color-mix(in oklch, var(--oklch-primary), white 15%);
--oklch-primary-muted: color-mix(in oklab, var(--oklch-primary), transparent 80%);
--oklch-success-hover: color-mix(in oklch, var(--oklch-success), white 15%);
--oklch-success-muted: color-mix(in oklab, var(--oklch-success), transparent 80%);
--oklch-danger-hover: color-mix(in oklch, var(--oklch-danger), white 15%);
--oklch-danger-muted: color-mix(in oklab, var(--oklch-danger), transparent 80%);
--oklch-warning-hover: color-mix(in oklch, var(--oklch-warning), white 10%);
--oklch-warning-muted: color-mix(in oklab, var(--oklch-warning), transparent 80%);
- Hover states: Use
oklchfor hue preservation during lightening - Muted states: Use
oklabfor perceptually uniform transparency
TypeScript color-mix() Utilities
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ COLOR-MIX UTILITY FUNCTIONS │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ colorMix(color1, color2, space, percent) │
│ └──► "color-mix(in {space}, {color1} {percent}%, {color2})" │
│ │
│ colorTransparent(color, opacity, space) │
│ └──► "color-mix(in {space}, {color}, transparent {100-opacity}%)"│
│ │
│ colorDarker(color, amount=30) │
│ └──► colorMix(color, "black", "oklab", 100-amount) │
│ │
│ colorLighter(color, amount=30) │
│ └──► colorMix(color, "white", "oklab", 100-amount) │
│ │
└───────────────────────────────────────────────────────────────────────┘
Copy
/**
* Generate CSS color-mix() string
* @param color1 First color (CSS value or variable)
* @param color2 Second color (CSS value or variable)
* @param space Color space for mixing
* @param percent Percentage of color1 (0-100)
*/
export function colorMix(
color1: string,
color2: string,
space: ColorMixSpace = "oklch",
percent: number = 50
): string {
return `color-mix(in ${space}, ${color1} ${percent}%, ${color2})`;
}
/**
* Generate transparent variant using color-mix
* @param color CSS color value or variable
* @param opacity Opacity 0-100
* @param space Color space (oklab recommended for transparency)
*/
export function colorTransparent(
color: string,
opacity: number,
space: ColorMixSpace = "oklab"
): string {
return `color-mix(in ${space}, ${color}, transparent ${100 - opacity}%)`;
}
/**
* Generate darker variant using color-mix
* Uses oklab for perceptually uniform darkening
*/
export function colorDarker(color: string, amount: number = 30): string {
return colorMix(color, "black", "oklab", 100 - amount);
}
/**
* Generate lighter variant using color-mix
* Uses oklab for perceptually uniform lightening
*/
export function colorLighter(color: string, amount: number = 30): string {
return colorMix(color, "white", "oklab", 100 - amount);
}
Color Space Decision Matrix
Copy
COLOR-MIX() COLOR SPACE DECISION MATRIX
--------------------------------------------------------------------
Operation Recommended Space Reason
=========================== ================= ================
Mix with white (lighten) oklch Preserves hue
Mix with black (darken) oklab Uniform darkening
Mix with transparent oklab Perceptual opacity
Mix with gray (desaturate) oklab Even chroma reduction
Mix two Core Colors oklab No muddy midpoints
Create hover state oklch Identity preservation
Create active state oklab Subtle darkening
Create disabled state oklab Desaturation
Create selection background oklab Clean transparency
Create gradient oklab Smooth transition
DEFAULT RULE: When in doubt, use oklab
EXCEPTION: When preserving hue is critical, use oklch
THE CENTER
How This Component Helps Visualize Information Flow
Copy
Connection to Core-Flow:
+-- Flow colors derive from Core using color-mix()
+-- OKLAB ensures perceptually uniform transitions
+-- No "muddy" colors when flowing between states
+-- Information intensity mapped to opacity levels
Transparency Patterns
Learn how transparency creates visual hierarchy through opacity gradients