CSSColor Values (hex, rgb, hsl, oklch)

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
/* 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:

CSS
/* 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:

CSS
/* 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:

CSS
/* 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 */
}
hsl() is ideal for building color palettes — keeping the hue constant and changing lightness/saturation creates visually coherent tints and shades
The hsl model maps closely to how we intuitively think about color. "I want a lighter blue" = increase the lightness. "I want a less saturated red" = decrease the saturation. This makes `hsl()` the best format for design systems that need a programmatic relationship between colors (like a 50-step palette).
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.

CSS
/* 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 */
oklch() is the recommended color format for new projects — it's perceptually uniform and works with the wider P3 color gamut on modern displays
Unlike `hsl()` which maps to the sRGB color space (the older, smaller one), `oklch()` can express colors in the P3 wide-gamut color space supported by modern iPhone and MacBook displays. Colors with high chroma values (above ~0.2-0.25 depending on hue) will display more vividly on P3 screens and fall back gracefully to sRGB. Use `@media (color-gamut: p3)` to serve P3 colors to capable displays.
Quick comparison

Format

Best for

Intuitive for

#hex

Compact, widely known

Copy-paste from design tools

rgb()

When you think in 0-255 channels

Mixing with JS

hsl()

Palette building, tint/shade relationships

Designers used to HSB/HSL

oklch()

Perceptually uniform palettes, P3 gamut

Advanced color systems, design tokens

Next
CSS custom properties — the variable system that makes design tokens and theming possible: [CSS Custom Properties (Variables)](/css/custom-properties).