CSS Color Formats Explained: HEX, RGB, HSL, and oklch
CSS supports a dozen color formats and choosing the wrong one makes your code harder to maintain. Learn when to use HEX, RGB, HSL, oklch, and CSS custom properties — with conversion formulas and practical tips.
HEX: #RRGGBB
The most common format for designers and developers. Three two-digit hex values for red, green, and blue, each ranging from 00 to FF.
color: #3B82F6; /* full form */ color: #38F; /* shorthand — each digit doubled: #3388FF */ color: #3B82F6CC; /* 8-digit: last 2 digits = alpha (CC = 80% opacity) */ color: #3388FFCC; /* shorthand with alpha */
Best for: Design tokens, copy-pasting from design tools (Figma exports HEX by default), CSS variables. Weakness: Hard to intuitively adjust lightness or saturation.
RGB / RGBA: rgb(R G B / A)
Three channels (0–255) for red, green, and blue. Optionally a fourth value for alpha (opacity), expressed as 0–1 or 0%–100%.
/* Modern space-separated syntax (CSS Color Level 4) */ color: rgb(59 130 246); color: rgb(59 130 246 / 0.8); /* 80% opacity */ color: rgb(59 130 246 / 80%); /* same */ /* Legacy comma syntax (still valid) */ color: rgb(59, 130, 246); color: rgba(59, 130, 246, 0.8);
Best for: Programmatic manipulation in JavaScript (split channels, apply calculations). Weakness: Unintuitive for humans — hard to know what “rgb(200 50 100)” looks like.
HSL / HSLA: hsl(H S% L% / A)
Hue (0–360°), Saturation (0–100%), Lightness (0–100%). The most human-friendly format — you can adjust lightness or saturation by changing a single number.
color: hsl(217 91% 60%); /* blue */
color: hsl(217 91% 40%); /* darker blue — only lightness changed */
color: hsl(217 91% 60% / 0.5); /* 50% transparent */
/* Great for generating palettes with CSS variables: */
:root {
--hue: 217;
--color-100: hsl(var(--hue) 91% 95%);
--color-500: hsl(var(--hue) 91% 60%);
--color-900: hsl(var(--hue) 91% 20%);
}Best for: Building design systems, generating tints/shades programmatically, theming. Weakness: Perceptually non-uniform — lightness 50% looks different across hues.
oklch: oklch(L C H / A)
The modern CSS color format introduced in CSS Color Level 4. Based on the Oklab perceptual color space, it solves the key weakness of HSL: it is perceptually uniform — equal lightness values actuallylook equally light across all hues.
/* oklch(Lightness Chroma Hue / Alpha) */
color: oklch(0.6 0.18 264); /* blue ~equivalent to #3B82F6 */
color: oklch(0.6 0.18 264 / 0.8); /* 80% opacity */
/* Consistent lightness across hues — HSL can't do this: */
.red { color: oklch(0.6 0.18 20); } /* same perceived lightness */
.green { color: oklch(0.6 0.18 140); } /* as blue below ↓ */
.blue { color: oklch(0.6 0.18 264); }Best for: New design systems in 2025+, accessible color palettes, dark mode that actually works. Support: All modern browsers (Chrome 111+, Firefox 113+, Safari 15.4+).
Quick Comparison
| Format | Readability | Adjustable | Perceptual | Best use |
|---|---|---|---|---|
| HEX | Medium | Hard | No | Design tokens, copy from Figma |
| RGB | Low | Easy in JS | No | Programmatic manipulation |
| HSL | High | Easy | Partial | Design systems, theming |
| oklch | Medium | Easy | Yes ✅ | Modern design systems, a11y |
Pairing Colors with CSS Custom Properties
Regardless of the format you choose, defining colors as CSS custom properties lets you maintain a single source of truth and swap themes without changing component code.
:root {
/* oklch palette — perceptually consistent across hues */
--color-primary: oklch(0.6 0.18 264);
--color-success: oklch(0.6 0.18 140);
--color-danger: oklch(0.6 0.18 20);
--color-warning: oklch(0.75 0.15 80);
}
@media (prefers-color-scheme: dark) {
:root {
/* Just adjust lightness for dark mode */
--color-primary: oklch(0.75 0.18 264);
--color-success: oklch(0.75 0.18 140);
}
}Convert between HEX, RGB, HSL, and oklch
Paste any color value and instantly get its equivalent in every CSS format — with a live color preview.
Open Color Converter →