CSS Color Formats: When to Use HEX, RGB, HSL, or Named Colors
CSS supports more color formats than most developers realise: named colors, hex codes, RGB, RGBA, HSL, HSLA, and the newer HWB, LCH, and Display P3 gamut formats. The format you choose affects readability, maintainability, and what operations you can perform in CSS. This guide covers when to use each.
Convert between all color formats: Our RGB/HEX/HSL Converter converts colors with a live preview โ type in any format and all others update instantly.
Open Color Converter โTable of Contents
HEX Codes
Hex codes (#FF5733) are the most common CSS color format and the default output of design tools like Figma, Sketch, and Photoshop. They specify red, green, and blue channels as two-digit hexadecimal values (00โFF). Short hex codes (#F53) expand each digit: #FF5533.
HEX is great for copy-pasting colors from design tools and for exact color values defined in a brand style guide. It's compact and universally supported. Its weakness is that it's completely opaque about what the color actually looks like โ #7CB9E8 tells you nothing about the hue or lightness without decoding the math.
CSS4 hex codes support alpha: #FF573380 (last two digits = alpha, 80 = 50% opacity). Less widely used than RGBA for opacity.
RGB and RGBA
RGB specifies red, green, and blue as decimal values (0โ255): rgb(255, 87, 51). RGBA adds an alpha channel: rgba(255, 87, 51, 0.5) for 50% transparency.
Use RGBA when you need transparency โ it's the most readable format for opacity values. The CSS Color Level 4 spec allows a slash syntax: rgb(255 87 51 / 50%) which unifies RGB and RGBA into one function.
HSL and HSLA
HSL defines colors as Hue (0โ360ยฐ), Saturation (0โ100%), and Lightness (0โ100%): hsl(14, 100%, 60%). This is the most human-intuitive format because it maps to how people actually think about color.
- Hue is the color wheel position: 0ยฐ/360ยฐ is red, 120ยฐ is green, 240ยฐ is blue
- Saturation is how vivid vs grey: 100% is fully saturated, 0% is greyscale
- Lightness is how light vs dark: 100% is white, 0% is black, 50% is the "true" color
Why HSL is superior for design systems
HSL makes color manipulation trivial in CSS. To create a hover state that's darker: change only the lightness. To create a disabled state that's less vivid: change only the saturation. With HEX or RGB, you'd need a different set of numbers for every variant.
/* HEX โ you need a separate value for every shade */
.btn { background: #2563EB; }
.btn:hover { background: #1D4ED8; }
.btn:active { background: #1E40AF; }
.btn:disabled { background: #93C5FD; }
/* HSL โ change only one parameter */
.btn { background: hsl(221, 83%, 53%); }
.btn:hover { background: hsl(221, 83%, 45%); } /* darker */
.btn:active { background: hsl(221, 83%, 38%); } /* darkest */
.btn:disabled { background: hsl(221, 83%, 80%); } /* lighter */
CSS Custom Properties with HSL
The most powerful pattern for theming is storing HSL components in CSS custom properties:
:root {
--brand-h: 221;
--brand-s: 83%;
--brand-l: 53%;
--brand: hsl(var(--brand-h), var(--brand-s), var(--brand-l));
}
/* Derive the full color scale automatically */
.text-brand-light { color: hsl(var(--brand-h), var(--brand-s), 70%); }
.text-brand { color: hsl(var(--brand-h), var(--brand-s), var(--brand-l)); }
.text-brand-dark { color: hsl(var(--brand-h), var(--brand-s), 35%); }
/* Dark mode: just change lightness */
@media (prefers-color-scheme: dark) {
:root {
--brand-l: 65%; /* lighter on dark backgrounds */
}
}
Named Colors
CSS supports 140 named colors: red, cornflowerblue, rebeccapurple, etc. Use them for prototyping, debugging, and utility code โ not production design systems. They're readable in code but imprecise for brand consistency.
currentColor
The currentColor keyword inherits the element's color property. Useful for making borders, SVG fills, and box shadows automatically match text color:
button {
color: #2563EB;
border: 2px solid currentColor; /* same blue as text */
box-shadow: 0 0 0 3px currentColor; /* focus ring */
}
Modern Color Spaces: oklch and oklab
All major browsers added support for the oklab and oklch color spaces in 2023 (Chrome 111, Firefox 113, Safari 15.4+). These are perceptually uniform color spaces โ meaning equal numerical steps produce equal perceived changes in lightness and chroma, which is not true for HSL.
oklab uses lightness (L), green-red axis (a), and blue-yellow axis (b):
/* oklab */
color: oklab(0.7 -0.1 0.1); /* a greenish color */
color: oklab(60% -0.1 0.1); /* same, percentage lightness */
oklch uses lightness (L), chroma (C), and hue (H) โ similar to HSL but perceptually uniform:
/* oklch */
color: oklch(70% 0.15 200); /* teal */
color: oklch(55% 0.2 30); /* orange */
/* oklch in design tokens */
:root {
--brand-hue: 200;
--brand: oklch(55% 0.18 var(--brand-hue));
--brand-light: oklch(75% 0.12 var(--brand-hue));
--brand-dark: oklch(35% 0.22 var(--brand-hue));
}
The key practical advantage of oklch over HSL: when you rotate the hue, the perceived brightness stays consistent. In HSL, yellow (60ยฐ) and blue (240ยฐ) appear dramatically different in brightness at the same lightness value. In oklch, equal L values are genuinely equal in perceived lightness โ making oklch the recommended format for generating accessible color palettes programmatically.
The color-mix() function (also widely supported since 2023) works with any color space and enables mixing colors in CSS without JavaScript:
/* Mix two colors 50/50 in oklch color space */
color: color-mix(in oklch, var(--brand) 50%, white);
/* Create a hover variant 20% lighter */
color: color-mix(in oklch, var(--brand) 80%, white);
Choosing a Format
| Use case | Recommended format |
|---|---|
| Copy from design tool | HEX |
| Need transparency | RGBA or HSLA |
| Design system / theming | HSL with CSS variables |
| Quick prototyping | Named colors |
| JavaScript color manipulation | RGB (easy to do math on integers) |
| Brand specification document | HEX + RGB (for print CMYK too) |
