Home · Blog · Colour

Colour theory basics for the web: hue, lightness and the models screens actually use

You do not need an art degree to use colour well on screen — you need three ideas: hue, saturation and lightness; an honest map of how RGB, HSL and OKLCH describe them; and the wheel relationships that make palettes feel deliberate. This is the working minimum, with numbers.

Every colour you will ever specify on the web is three numbers wearing different costumes. In #FF7A29 the numbers are red, green and blue channels. In hsl(26 100% 58%) they are hue, saturation and lightness. In oklch(0.70 0.18 47) they are lightness, chroma and hue in a perceptually uniform space. The colour did not change between those spellings — what changed is how easy the numbers are to reason about. Most colour mistakes on the web are really model mistakes: adjusting the wrong number for the effect you want.

This article builds the mental model first — what the eye responds to, how the wheel organises hue, and where each CSS colour model earns its keep — because palettes, gradients and contrast fixes all get easier once the coordinates make sense.

Key takeaways

  • Hue says which colour family; saturation (or chroma) says how intense; lightness says how bright. Separating the three is the whole game.
  • HSL is easy to picture but lies about brightness: equal lightness values in different hues do not look equally bright. OKLCH fixes that.
  • The classic wheel relationships — complementary, analogous, triadic — are recipes for hue spacing, not guarantees of quality.
  • On screens, contrast is carried mostly by lightness difference. Get lightness right and hue choices become a matter of taste.

Three dials, not one colour

Think of colour as three independent dials. Hue is an angle on a wheel: 0° is red, 120° green, 240° blue, and the web's brand orange sits near 26–47° depending on the model. Saturation is intensity — the distance from grey: a desaturated red is a dusty brick, fully saturated it is a warning light. Lightness is position between black and white. Nearly every practical operation maps to one dial: "make it pop" is usually saturation, "make it readable" is always lightness, "make it match the brand" is hue.

The dials interact through perception. Yellow at full saturation looks dramatically lighter than blue at the same numerical lightness, because the eye's sensitivity peaks in the green-yellow range. This is why rainbow palettes at uniform HSL lightness look chaotic — the numbers agree, the eyes do not — and why perceptually uniform models were invented.

The models, compared as tools

ModelExample (brand orange)Good atTrap
HEX / RGB#FF7A29Exact specification; what design tools and code exchangeHopeless for adjustments — nudge one channel and hue, saturation and lightness all move
HSLhsl(26 100% 58%)Quick mental edits: spin hue, mute saturation, darken for hover statesLightness is not perceived lightness; 50% yellow and 50% blue look nothing alike in brightness
HSV / HSBhsb(26 84% 100%)Colour pickers; picking a pure hue then a shadeBrightness maxes out per-hue, so comparing across hues misleads just like HSL
OKLCHoklch(0.70 0.18 47)Palettes and ramps: equal steps look equal; lightness predicts contrast honestlyCan specify colours outside screen gamut — browsers clamp, sometimes surprisingly

A practical workflow uses each where it is strong: receive colours as hex, explore and build ramps in OKLCH (its lightness scale is the one your eyes use), and sanity-check any text pairing with a contrast tool, because no model excuses you from the ratio.

Wheel relationships, demystified

The harmony rules are spacing patterns on the hue wheel. Complementary colours sit opposite (180° apart) and maximise mutual intensity — blue and orange is the classic, which is why it covers half the film posters ever printed. Analogous colours cluster within about 60° and feel calm and unified. Triadic schemes space three hues 120° apart for balanced variety; split-complementary takes a hue and the two neighbours of its opposite, keeping the tension with less risk of a fight.

What the wheel cannot tell you is proportion and lightness, which is where schemes are won. A working screen palette usually assigns roles rather than equal shares: one dominant family for surfaces, a supporting family for secondary elements, and a small, high-chroma accent reserved for the few things that must be noticed. Two fully saturated complementary hues at similar lightness, used evenly, vibrate against each other — the wheel said they harmonise, and they do, the way two loud voices harmonise.

Lightness: the dial that does the real work

Interfaces are read in lightness long before they are admired in hue. Text, dividers, hover states, disabled states and elevation are all lightness steps within a hue family. Build a ramp for one hue in OKLCH — say lightness 0.97, 0.93, 0.85, 0.70, 0.55, 0.40, 0.25 at roughly constant chroma — and you have backgrounds, borders, secondary text and primary text that share an identity and a legible order. When a design feels "off" but the hues match the brand, it is almost always the lightness steps that are uneven, too close together, or fighting the text placed on them.

Mistakes and pitfalls

Designing in HSL and trusting its lightness

HSL lightness is an arithmetic midpoint of the RGB channels, not a perceptual measure. Two swatches at hsl lightness 50% can differ enormously in perceived brightness, which silently breaks any ramp built on equal steps.

Choosing colours by name instead of by number

"Our blue" drifts between screens, tools and teammates. A palette survives hand-offs only as numbers in a named model — tokens like --brand-500: oklch(...) — never as adjectives.

Using saturation to fix a contrast problem

A pale yellow and a vivid yellow fail against white at similar rates, because the failure is lightness. Cranking saturation makes failing text louder, not more legible. Move lightness until the ratio passes, then tune chroma for taste.

Common questions

Should I switch everything to OKLCH?

For building palettes and ramps, it is the best tool CSS has ever offered and support is now broad. For exchanging colours with the wider world, hex remains the lingua franca. Use OKLCH to think, hex to hand over.

Why does the same hex look different on my two monitors?

Because hex specifies numbers, not appearance, and monitors differ in gamut, calibration and brightness. Wide-gamut displays oversaturate unmanaged sRGB content in particular. You cannot fully control this; you can keep important distinctions in lightness, which survives display differences better than subtle hue shifts.

How many colours should a site have?

Fewer than instinct suggests: one primary family with a lightness ramp, one supporting or neutral family, a small accent, and semantic colours for success, warning and error. Most "colourful" interfaces that feel chaotic are actually undisciplined lightness, spread across too many hues.

To wrap up

Colour theory for the web reduces to a workable discipline: name the three dials, pick the model that tells the truth about the dial you are turning — OKLCH for lightness — and let wheel relationships suggest hue spacings while lightness and proportion do the heavy lifting. With that in place, palettes, gradients and accessible text are variations on one skill.

Try it yourself

The colour studio shows one colour as HEX, RGB, HSL and OKLCH simultaneously, which is the fastest way to build intuition for how the models relate — pick a colour and watch all four readouts move.

Open the Colour Studio