DEV Community

Snappy Tools
Snappy Tools

Posted on

CSS Color Formats: Hex, RGB, HSL, and When to Use Each

CSS supports more color formats than most developers use. Knowing when to reach for hex vs HSL vs oklch affects readability, maintainability, and how easily you can manipulate colors in code.

Hex

The most widely used format. A 6-digit hexadecimal value representing red, green, and blue channels:

color: #3b82f6;  /* blue */
color: #ff0000;  /* red */
color: #000000;  /* black */
color: #ffffff;  /* white */
Enter fullscreen mode Exit fullscreen mode

Each pair represents a channel from 00 (0) to ff (255). You can also use 3-digit shorthand when each pair is a repeated digit:

color: #fff;   /* same as #ffffff */
color: #000;   /* same as #000000 */
color: #f00;   /* same as #ff0000 */
Enter fullscreen mode Exit fullscreen mode

With alpha (transparency): append two more hex digits (00–ff):

color: #3b82f680;  /* 50% opacity blue */
color: #00000040;  /* 25% opacity black */
Enter fullscreen mode Exit fullscreen mode

When to use hex: copying from design tools (Figma, Sketch export hex), existing codebases that use hex, when brevity matters more than readability.

To convert between hex and other formats, the Color Picker shows all representations simultaneously — paste any format and get the others.

RGB

Explicit red, green, blue channels from 0–255:

color: rgb(59, 130, 246);        /* blue */
color: rgba(59, 130, 246, 0.5);  /* 50% opacity blue */

/* Modern syntax — alpha as optional 4th value */
color: rgb(59 130 246);
color: rgb(59 130 246 / 50%);
color: rgb(59 130 246 / 0.5);
Enter fullscreen mode Exit fullscreen mode

The modern rgb(r g b / alpha) syntax (no commas) is now widely supported and preferred over rgba(). Both work.

When to use RGB: when you need to manipulate individual channels in JavaScript, or when working with color values from an API or sensor data.

// Useful for dynamic colors in JavaScript
const r = 59, g = 130, b = 246;
element.style.color = `rgb(${r} ${g} ${b})`;
Enter fullscreen mode Exit fullscreen mode

HSL

Hue, Saturation, Lightness — the most human-intuitive format:

color: hsl(217, 91%, 60%);        /* blue */
color: hsl(217 91% 60%);          /* same, modern syntax */
color: hsl(217 91% 60% / 0.5);    /* 50% opacity */
Enter fullscreen mode Exit fullscreen mode
  • Hue: 0–360, the color wheel position (0=red, 120=green, 240=blue)
  • Saturation: 0% (grey) to 100% (fully saturated)
  • Lightness: 0% (black) to 100% (white)

Why HSL is better for code:

You can intuitively derive color variations by adjusting a single value:

.button {
  background: hsl(217 91% 60%);
}
.button:hover {
  background: hsl(217 91% 50%);  /* darker — just change lightness */
}
.button:disabled {
  background: hsl(217 20% 70%);  /* desaturated — just change saturation */
}
Enter fullscreen mode Exit fullscreen mode

Try doing that with hex. You can't, at least not without calculating the new hex value.

When to use HSL: when creating color systems, theme variations, or any time you need to programmatically derive related colors. Also excellent with CSS custom properties:

:root {
  --brand-hue: 217;
  --brand-saturation: 91%;
}

.primary   { color: hsl(var(--brand-hue) var(--brand-saturation) 60%); }
.primary-dark  { color: hsl(var(--brand-hue) var(--brand-saturation) 45%); }
.primary-light { color: hsl(var(--brand-hue) var(--brand-saturation) 75%); }
Enter fullscreen mode Exit fullscreen mode

HWB

Hue, Whiteness, Blackness — a newer format (CSS Color Level 4):

color: hwb(217 20% 10%);
Enter fullscreen mode Exit fullscreen mode

Less commonly used but can be more intuitive for mixing colors with white or black.

oklch

The most modern and perceptually accurate format:

color: oklch(65% 0.2 264);  /* blue */
Enter fullscreen mode Exit fullscreen mode
  • L: lightness 0–1 (or 0%–100%)
  • C: chroma (saturation), roughly 0–0.4
  • H: hue angle 0–360

Why oklch is better than HSL: HSL's lightness is not perceptually uniform. hsl(60 100% 50%) (yellow) appears much brighter than hsl(240 100% 50%) (blue) despite both having 50% lightness. oklch uses the OKLab color space which is calibrated to human perception — colors at the same lightness value actually look equally bright.

/* These actually look the same lightness in oklch */
.yellow { color: oklch(80% 0.18 105); }
.blue   { color: oklch(80% 0.18 264); }
.pink   { color: oklch(80% 0.18 350); }

/* In HSL, you'd need to manually adjust each */
Enter fullscreen mode Exit fullscreen mode

Browser support: oklch is supported in all modern browsers (Chrome 111+, Firefox 113+, Safari 15.4+). Not supported in IE.

When to use oklch: new projects targeting modern browsers, design systems requiring perceptual color uniformity, when you want accessible color palettes.

Color accessibility

For text on backgrounds, contrast ratio matters. The WCAG 2.1 standard requires:

  • 4.5:1 for normal text (AA)
  • 3:1 for large text (AA)
  • 7:1 for normal text (AAA)

The Color Contrast Checker calculates the ratio between any two colors and shows WCAG AA/AAA pass/fail — paste hex, RGB, or HSL values directly.

Choosing a format

Format Use when
hex Design tool export, existing hex-based codebases, brevity
rgb JavaScript color manipulation, channel-level math
hsl Color variations, themes, readable color systems
oklch Perceptually uniform palettes, modern browsers only

One practical approach: use hex for static brand colors, HSL for dynamic variations (hover states, dark mode), oklch when you're building a full design system and need perceptual uniformity.

Consistent usage

Whichever format you choose, be consistent. Mixing hex and HSL across a codebase means every developer has to mentally translate between formats. If using CSS custom properties, define all base colors in one format:

:root {
  /* All colors defined once, in one format */
  --blue-500: hsl(217 91% 60%);
  --blue-600: hsl(217 91% 50%);
  --green-500: hsl(142 71% 45%);
  --red-500: hsl(0 84% 60%);
}
Enter fullscreen mode Exit fullscreen mode

Hex is convenient for copying from design tools. HSL is the most practical for code-driven color systems. oklch is the future for perceptual accuracy. The choice depends on your project's needs — but knowing all three lets you make the call deliberately rather than defaulting to hex out of habit.

Top comments (0)