CSS gives you four main ways to specify a colour: HEX, RGB/RGBA, HSL/HSLA, and the new Color Level 4 formats like oklch. Most developers pick one format early and stick with it everywhere — usually HEX — without thinking much about it.
But each format has genuine advantages. Here's what they are and when to reach for each one.
HEX (#RRGGBB)
The most common format. Six hexadecimal digits representing the red, green, and blue channels, each from 00 to ff.
color: #2f855a; /* green */
color: #1a1a2e; /* dark blue */
color: #fff; /* white (shorthand) */
color: #000; /* black (shorthand) */
3-digit shorthand: When each pair of digits is identical, you can shorten it — #ff6600 becomes #f60, #ffffff becomes #fff.
With alpha (8-digit): #RRGGBBAA — the last two digits are the alpha channel.
color: #2f855a80; /* 50% transparent green */
When to use HEX:
- Copying colours from Figma, Sketch, or any design tool (they output HEX by default)
- When working from brand style guides (usually specify HEX)
- When consistency with existing codebase is more important than readability
RGB and RGBA
Specifies red, green, and blue channels as numbers from 0 to 255, with an optional alpha from 0 to 1.
color: rgb(47, 133, 90);
color: rgba(47, 133, 90, 0.5); /* 50% transparent */
color: rgba(0, 0, 0, 0.1); /* 10% black overlay */
Modern CSS also accepts the newer space-separated syntax without the function prefix:
color: rgb(47 133 90);
color: rgb(47 133 90 / 50%); /* alpha as percentage */
When to use RGB:
- When alpha transparency is needed and you find
rgba()more readable than 8-digit HEX - When you're doing colour calculations in JavaScript (
canvas,getComputedStyle()) — JavaScript returns RGB values - When you're working with colours defined as separate channel values (common in game engines and design APIs)
HSL and HSLA
Hue, Saturation, and Lightness. A more intuitive system for humans to reason about colour.
color: hsl(145, 47%, 35%); /* the same green as #2f855a */
color: hsl(145, 47%, 35%, 0.5); /* 50% transparent */
color: hsl(145 47% 35% / 50%); /* modern syntax */
The three values:
- Hue (H): 0°–360°, the colour wheel position (0° = red, 120° = green, 240° = blue)
- Saturation (S): 0% = grey, 100% = fully saturated
- Lightness (L): 0% = black, 50% = "normal", 100% = white
Why HSL is so useful for UI work:
The real power of HSL is that you can derive tints and shades by only changing the lightness value:
:root {
--green-base: 145 47%; /* hue + saturation */
--green-100: hsl(var(--green-base) 95%);
--green-200: hsl(var(--green-base) 85%);
--green-500: hsl(var(--green-base) 50%);
--green-700: hsl(var(--green-base) 35%);
--green-900: hsl(var(--green-base) 20%);
}
This produces a full colour scale from a single hue and saturation pair. Much easier to maintain than a list of HEX values.
When to use HSL:
- Building design tokens and colour palettes
- Generating hover states (
lightness + 10%) or disabled states (lightness + 20%) - Darkmode: you can flip lightness values consistently
- Any time you want the colour scale to be derived rather than hardcoded
Color Level 4: oklch() and oklab()
These are newer CSS formats that better match human colour perception. The main advantage: equal steps in the values produce visually equal differences in the rendered colour — which is not true of HSL.
color: oklch(55% 0.15 145); /* similar to the green above */
The three channels: Lightness (0–1), Chroma (0–0.4+), and Hue (0°–360°).
Currently supported in: Chrome 111+, Firefox 113+, Safari 15.4+. Check caniuse.com before using in production without a fallback.
Converting between formats
If you have a HEX colour from a design file and want to convert it to HSL for your CSS variables:
- Paste it into the Color Picker at SnappyTools — it converts between HEX, RGB, HSL, and CMYK instantly, with the eyedropper tool to sample any colour from your screen.
- In CSS preprocessors: Sass has
color.adjust()andcolor.scale()functions. - In JavaScript: use a colour library like
chroma.jsorcolor2kfor programmatic conversions.
Quick reference
| Format | Opacity support | Human-readable | Best for |
|---|---|---|---|
| HEX | 8-digit version | Low | Copying from design tools |
| RGB | rgba() |
Medium | JavaScript operations |
| HSL | hsla() |
High | Colour palettes, design tokens |
| oklch | Inline | Medium | Perceptually uniform scales |
The practical recommendation
Use HSL for your design system's colour tokens and utility classes — it's far easier to reason about and generate tints/shades programmatically. Use HEX when copying from design files or when the existing codebase uses HEX throughout. Use RGBA when you specifically need transparency and want the syntax to be explicit.
For most CSS projects, mixing formats is fine — browsers normalise everything internally. Pick whichever format is most readable in context.
Top comments (0)