Guide

CSS colour formats explained: HEX, RGB, HSL, HWB and OKLCH

What each CSS colour format means, when to use it, why OKLCH is useful for palettes, and how to check colour contrast for accessibility.

How we made this: Technical explainer based on the CSS Color Module Level 4 specification and WCAG 2.2 contrast requirements. Browser support notes reflect current stable browsers at the time of writing. Editorial policy.

CSS gives you several ways to write the same colour. They describe the colour from different angles, and choosing the right one makes colours easier to read, adjust and keep accessible.

Convert any colour: paste a value into the colour converter to get every format and a WCAG contrast check.

HEX: compact and universal

#3446d4 is three bytes in hexadecimal: red 34, green 46 and blue d4, each from 00 to ff (0–255). Short forms double each digit (#fff = #ffffff). A fourth or eighth digit adds alpha: #3446d480 is about 50% opaque.

Use it when you’re copying colours between tools, or for brand values. It’s hard to adjust by eye.

RGB: the same thing in decimal

rgb(52 70 212) is the same colour as #3446d4. Modern syntax separates values with spaces and adds alpha after a slash: rgb(52 70 212 / 50%). The older rgba(52, 70, 212, 0.5) still works.

HSL: hue, saturation, lightness

hsl(233 65% 52%) (our #3446d4 again): the hue is an angle on the colour wheel (0 red, 120 green, 240 blue), saturation is from grey to vivid, and lightness is from black through the pure colour to white.

Use it when you want quick hand adjustments, such as a lighter tint or a less saturated version. Its weakness: lightness isn’t perceived lightness. hsl(60 100% 50%) (yellow) looks far brighter than hsl(240 100% 50%) (blue), despite the same “50%”.

HWB: hue, whiteness, blackness

hwb(233 20% 17%) starts from a pure hue and mixes in white and black, a bit like mixing paint. It’s intuitive for picking tints and shades, but less common in codebases.

OKLCH: perceptual lightness, chroma, hue

oklch(50% 0.2 270) uses the OKLab colour space (Björn Ottosson, 2020), which is designed so equal numeric steps look like equal visual steps:

  • L (lightness), 0–100%: perceived lightness. Two colours at 70% look about equally light, whatever their hue.
  • C (chroma), from 0 upwards (usually up to about 0.37): colourfulness. 0 is grey.
  • H (hue), 0–360°: the hue angle. It doesn’t line up exactly with HSL’s.

This makes OKLCH excellent for design systems. Keep L and C fixed and rotate H, and you get a set of accent colours with matching weight. Step L from 95% to 25%, and you get a tint-to-shade scale that looks even. It’s supported in current Chrome, Edge, Firefox and Safari.

One catch: OKLCH can describe colours that ordinary sRGB screens can’t show, especially at high chroma. Browsers map these to the nearest displayable colour, and wide-gamut (Display P3) screens can show more of them. The colour converter works in sRGB, and flags colours it had to clamp.

Contrast: making text readable

WCAG 2.x measures contrast as a ratio of the relative luminance of two colours, from 1:1 (identical) to 21:1 (black on white):

ContentAAAAA
Normal text4.5:17:1
Large text (≈24px, or ≈19px bold)3:14.5:1
UI components and graphics3:1—

Values near the threshold matter. #777777 on white is 4.48:1 and fails AA for body text. #767676 is 4.54:1 and passes. Check real colour pairs instead of guessing. Semi-transparent text is checked after blending it with its background.

A newer contrast method, APCA, is being explored for future versions of WCAG. For now, the WCAG 2.x ratio is the one in standards and legal requirements.

A practical workflow

  1. Choose your brand colour in any format, and convert it to OKLCH with the colour converter.
  2. Build a scale by changing lightness in even steps, keeping chroma and hue similar. Lower the chroma slightly at the extremes, so colours stay in gamut.
  3. Check every text and background pair you plan to use for contrast. Keep a note of which pairs pass AA.
  4. Store the values as CSS custom properties. The converter can copy them in that form.
:root {
  --brand-500: oklch(52% 0.2 268);
  --brand-700: oklch(38% 0.16 268);
  --text-on-brand: oklch(98% 0.01 268);
}

Frequently asked questions

Which colour format should I use in CSS?

Any format works in modern browsers. Hex is compact and universal; HSL or OKLCH make it easier to adjust colours by hand and to build consistent scales. Many teams store design tokens in OKLCH and keep hex for compatibility.

What contrast ratio do I need?

WCAG 2.2 level AA requires at least 4.5:1 for normal text and 3:1 for large text (about 24px, or 19px bold) and for important UI parts like input borders and icons. Level AAA requires 7:1 for normal text.

Why do two colours with the same HSL lightness look different?

HSL lightness is a simple maths transformation of RGB, not how bright a colour looks. Yellow at 50% lightness looks much brighter than blue at 50%. OKLCH’s lightness is designed to match perception much more closely.

Tools mentioned

GitHub Copilot

AI Coding

GitHub’s AI pair programmer. It suggests code as you type and offers a chat assistant inside popular code editors and on GitHub itself.

Main use
Writing boilerplate faster
Free plan
Not yet verified
Pricing
Not yet verified
Last reviewed
Not yet reviewed

Cursor

AI Coding

An AI-first code editor built on the same foundations as Visual Studio Code. It lets you chat with your codebase and ask the AI to make…

Main use
Refactoring
Free plan
Not yet verified
Pricing
Not yet verified
Last reviewed
Not yet reviewed

You may also need

Free tools and pages that help with the same job.

Explore categories