Three notations, one colour
- HEX (
#6366F1): compact and easy to copy, the CSS default; - RGB (
rgb(99, 102, 241)): 0–255 per channel, convenient for computation and interpolation; - HSL (
hsl(239, 84%, 67%)): hue / saturation / lightness, closest to human intuition, best for designing palettes.
Reference colours
| Colour | HEX | RGB | HSL |
|---|---|---|---|
| Red | #FF0000 | 255, 0, 0 | 0, 100%, 50% |
| Mid grey | #808080 | 128, 128, 128 | 0, 0%, 50% |
| Brand blue | #6366F1 | 99, 102, 241 | 239, 84%, 67% |
| Dark background | #0F172A | 15, 23, 42 | 222, 47%, 11% |
Why contrast is not optional
WCAG requires a contrast ratio of at least 4.5:1 for body text, 3:1 for text at 18pt+ or bold headings, and 3:1 for non-text elements such as icons and borders. Light grey text on white looks elegant but often lands under 3:1, effectively invisible outdoors or for older users.
Practical advice
- Build scales with HSL: keep H and S fixed and vary only L (95% / 85% / 70% / 50%) for a harmonious ramp;
- Pick dark-mode colours separately: inverting a light theme overexposes or muddies it, choose background and foreground deliberately;
- Interactive states count too: hover, disabled and input borders all affect readability;
- Do not eyeball it: run a contrast checker, the cost is near zero.
Common questions
Why can #FFF be shortened? Only when both digits of all three channels match (#FFFFFF → #FFF); #F0F0F0 cannot. What is 8-digit HEX? The last two digits are alpha, so #6366F180 is roughly 50% opaque.
A practical palette workflow
- Pick the primary hue: choose one hue in HSL and keep saturation fixed (say 70%);
- Build the levels: vary only lightness L, page background (97%), card (99%), primary (55%), accent (45%), body text (25%);
- Check contrast: confirm text against its background reaches 4.5:1; if not, widen the L gap;
- Then the functional colours: one hue each for success, warning and error, each with a light and a dark variant so dark mode can reuse them.
Three common mistakes
- Light grey text on white: looks refined, but contrast is often under 3:1 and readability suffers;
- Inverting colours for dark mode: it blows out or muddies the palette, choose lightness per level instead;
- Judging by eye: eyes are poor at judging luminance ratios, so verify with a contrast calculator.
Colour vision deficiency and alternative encoding
- Do not signal state with red/green alone: it is the most common confusion pair, pair error and success with icons or text;
- Grey-scale self-check: convert the UI to grey and see whether the information still reads, the cheapest test available;
- Check both themes: passing in light mode does not imply dark mode passes; validate both token sets;
- Chart palettes: differentiate series by lightness as well as hue, and label the data.
Opacity and contrast
Compute contrast against the effective rendered colour, not the declared value of a translucent one. White text at 80% opacity over a light image can fall far below 4.5:1, add a scrim or solid background, then re-check.
Focus states must stay visible
Keyboard users navigate by the focus ring; removing it with outline: none requires an equivalent visible replacement, such as a custom outline in a contrasting colour. Focus indicators need 3:1 contrast too, or keyboard users are locked out, one of the most frequently flagged accessibility issues.
Try them: Color converter, Base converter