Color Values (hex, rgb, hsl, oklch)
CSS supports several ways to specify color — from the familiar six-digit hex code to the perceptually uniform oklch() color space introduced in 2023. Each format has different strengths. Hex is compact; hsl() makes color relationships intuitive; oklch() produces the most visually consistent results when manipulating colors programmatically.
Named colors
/* CSS has 148 named colors */ color: red; color: dodgerblue; color: tomato; color: rebeccapurple; color: transparent; /* = rgba(0,0,0,0) */ color: currentColor; /* inherits the element's text color */ /* Named colors are great for quick prototyping, not for production palettes */
Hex colors
Hex notation is the most widely used color format in CSS. Each pair of hex digits represents a red, green, and blue channel on a 0–255 scale:
/* Full 6-digit hex: #RRGGBB */ color: #0066cc; /* R=00, G=66, B=cc */ color: #ffffff; /* white */ color: #000000; /* black */ /* Short 3-digit hex — each digit is doubled */ color: #09c; /* same as #0099cc */ color: #fff; /* same as #ffffff */ color: #000; /* same as #000000 */ /* 8-digit hex with alpha: #RRGGBBAA */ color: #0066ccff; /* fully opaque */ color: #0066cc80; /* ~50% transparent (80 hex = 128 = 50% of 255) */ /* 4-digit short hex with alpha */ color: #09c8; /* same as #0099cc88 */
rgb() and rgba()
rgb() expresses colors as red, green, blue channels on a 0–255 scale. Modern CSS allows a single rgb() function to include an optional alpha via a slash:
/* Modern syntax — comma-less with optional alpha */ color: rgb(0 102 204); color: rgb(0 102 204 / 0.8); /* 80% opaque */ color: rgb(0 102 204 / 50%); /* 50% opaque */ /* Legacy syntax — commas, separate rgba() function */ color: rgb(0, 102, 204); color: rgba(0, 102, 204, 0.8); /* Both syntaxes are valid — modern is cleaner */ /* Percentage values are also allowed */ color: rgb(0% 40% 80%);
hsl() — intuitive color manipulation
hsl() stands for hue, saturation, lightness. The hue is an angle on the color wheel (0° = red, 120° = green, 240° = blue); saturation is the intensity; lightness is the brightness. What makes hsl() powerful is that you can create color palettes by keeping the hue constant and varying lightness:
/* hsl(hue saturation lightness) */
color: hsl(210 100% 40%); /* deep blue */
color: hsl(210 100% 40% / 0.8); /* same, 80% opaque */
/* Legacy comma syntax */
color: hsl(210, 100%, 40%);
color: hsla(210, 100%, 40%, 0.8);
/* Creating a palette from a single hue */
:root {
--hue: 210;
--color-900: hsl(var(--hue) 80% 20%); /* very dark */
--color-700: hsl(var(--hue) 70% 35%); /* dark */
--color-500: hsl(var(--hue) 60% 50%); /* mid */
--color-300: hsl(var(--hue) 60% 70%); /* light */
--color-100: hsl(var(--hue) 50% 90%); /* very light */
}
/* Darkening / lightening programmatically */
.btn {
background: hsl(210 70% 45%);
}
.btn:hover {
background: hsl(210 70% 38%); /* same hue, darker */
}oklch() — perceptually uniform color
oklch() is the modern standard for high-quality color work. It operates in a perceptually uniform color space — meaning equal changes in the values produce equal perceived changes in the color. Unlike hsl(), where changing the lightness of yellow and blue by the same amount produces noticeably different results, oklch() adjustments feel consistent across all hues.
/* oklch(lightness chroma hue) */
/* lightness: 0 (black) to 1 (white) */
/* chroma: 0 (grey) to ~0.37+ (vivid) */
/* hue: 0-360 degrees */
color: oklch(0.55 0.2 264); /* a vibrant blue */
color: oklch(0.7 0.15 145); /* a medium green */
color: oklch(0.9 0.05 80); /* a light warm yellow */
/* With alpha */
color: oklch(0.55 0.2 264 / 0.8);
/* Perceptually uniform palettes */
:root {
--brand-hue: 264; /* blue-violet */
--palette-1: oklch(0.20 0.15 var(--brand-hue));
--palette-2: oklch(0.35 0.18 var(--brand-hue));
--palette-3: oklch(0.50 0.20 var(--brand-hue)); /* mid — use for buttons */
--palette-4: oklch(0.65 0.18 var(--brand-hue));
--palette-5: oklch(0.80 0.12 var(--brand-hue));
--palette-6: oklch(0.92 0.05 var(--brand-hue));
}
/* Each step looks equally different from the previous — unlike hsl() palettes */Quick comparison
Format | Best for | Intuitive for |
|---|---|---|
| Compact, widely known | Copy-paste from design tools |
| When you think in 0-255 channels | Mixing with JS |
| Palette building, tint/shade relationships | Designers used to HSB/HSL |
| Perceptually uniform palettes, P3 gamut | Advanced color systems, design tokens |