Tags: web-dev ux concept

Colour Systems

Date: 2026-08-16


A structured palette plus the semantic names that point into it. The structure exists so contrast is guaranteed rather than checked, and the naming exists so a rebrand doesn’t require rereading every use.


A colour system is a set of colour scales, a set of role-based names mapping onto them, and rules about which combinations are permitted.

Three parts, and most “colour palettes” only have the first.

Scales, not colours

A brand colour alone is unusable — you need the same hue at many lightnesses for borders, backgrounds, hovers and text.

blue.50    lightest — page backgrounds
blue.100   subtle fills
blue.200   borders
blue.300
blue.400
blue.500   the brand colour
blue.600   hover / darker action
blue.700
blue.800
blue.900   text on light backgrounds
blue.950   darkest

Numbering by lightness rather than by order is what makes scales interchangeable — red.600 and blue.600 are equally dark, so swapping one for another doesn’t break contrast.

Generating them properly

Naive scales — lightening and darkening in sRGB — produce steps that look uneven and hues that drift.

sRGB manipulation
  perceptually uneven steps
  hue shifts, especially in blues
  no guarantee about contrast

OKLCH  (lightness, chroma, hue)
  L maps to perceived lightness
  even steps look even
  hue stays put when L changes

OKLCH is the practical reason to care about colour spaces. Fix the hue, step the lightness evenly, and the scale is perceptually uniform — which means a fixed numeric step also gives a predictable contrast step.

Semantic naming

The argument, stated plainly:

--red-500        what the colour IS
--colour-danger  what the colour is FOR

Components reference the second. The first becomes an implementation detail of the theme — Design Tokens.

The test for whether you’ve named correctly: could the value change without the name becoming a lie? --colour-danger can become orange. --red-500 cannot.

Roles worth defining before anything else:

surface        page and card backgrounds
text           default, muted, inverse
action         primary interactive
border         default, strong, subtle
focus          the focus indicator
danger · warning · success · info

Contrast is the constraint, not a check

Text and interactive elements have minimum contrast requirements — 4.5:1 for body text, 3:1 for large text and for UI component boundaries under WCAG AA.

Build the guarantee into the scale. If 600 and above always clear 4.5:1 on your lightest surfaces, “which blue for this text” stops being a question anyone has to answer.

                    on white
blue.400   2.6:1    ✗ fails body text
blue.500   3.9:1    ✗ fails body, ok for UI
blue.600   5.2:1    ✓
blue.700   7.4:1    ✓

Publish that table. A palette shipped without contrast figures guarantees somebody uses blue.400 for body text — WCAG, Inclusive Design.

Dark mode is not inversion

Flipping lightness produces harsh, over-saturated results, because dark surfaces need lower chroma and because pure white on pure black causes halation.

LIGHT                DARK
surface   white      near-black, not #000
text      near-black off-white, not #fff
action    blue.600   blue.400
                     ↑ LIGHTER, because
                       contrast reverses

The semantic layer is what makes this cheap — same names, different mappings. Without it, dark mode is a second stylesheet — Theming.

Where it goes wrong

  • Too many scales. Eleven steps across nine hues is ninety-nine colours nobody can hold in their head. Most systems need one brand scale, one neutral scale, and four status colours
  • Neutrals ignored. The grey scale carries more of the interface than the brand colour, and an untuned grey scale is what makes a UI look cheap. Slightly tinting neutrals towards the brand hue is a reliable improvement
  • Colour as the only signal. Status shown by colour alone excludes colour-blind users and fails in greyscale — pair it with an icon or text
  • No focus colour. It gets picked ad hoc, and it’s the one colour with a hard accessibility requirement