Home/Converters/Colour converter

Converter

Colour Converter

HEX, RGB and HSL, all linked to one swatch. Alongside the usual conversion, this works out the actual WCAG contrast ratio against black and white text — using the proper relative-luminance formula, not a naive brightness average.

This colour

#3366CC

rgb(51, 102, 204) · hsl(220, 60%, 50%)

Contrast vs black text
Contrast vs white text
WCAG AA (4.5:1 normal text)
WCAG AA (3:1 large/bold text)

Contrast is measured in relative luminance, not brightness

A quick-and-dirty "brightness" check averages R, G and B equally. The WCAG formula does not, because the human eye is far more sensitive to green than to blue. Each channel is first converted from sRGB's gamma-encoded 0–255 value to a linear value, then combined with weights that reflect that sensitivity:

The WCAG relative luminance formula, applied per channel then combined
1. Normalisec = channel ÷ 255
2. Linearisec ≤ 0.03928 → c ÷ 12.92, else → ((c + 0.055) ÷ 1.055)^2.4
3. CombineL = 0.2126·R + 0.7152·G + 0.0722·B
4. Contrast ratio(L₁ + 0.05) ÷ (L₂ + 0.05), lighter over darker

Pure white against pure black comes out to exactly 21:1 — the maximum possible — which is a useful sanity check for any implementation of this formula, including this one.

The channel weights are why pure blue and pure green, both fully saturated primaries, behave completely differently as backgrounds. Pure blue (#0000FF) has a relative luminance of just 0.072 — closer to black than to grey — giving it 2.4:1 contrast against black text but 8.6:1 against white. Pure green (#00FF00) is the opposite: luminance 0.715, close to white, so it contrasts well with black text (15.3:1) and poorly with white (1.4:1). A brightness-average formula would treat both as roughly equal; the real formula does not, because they are not equally visible.

WCAG's actual thresholds

WCAG 2.x contrast requirements for text readability
LevelText sizeMinimum ratio
AANormal text4.5 : 1
AALarge text (18pt+/14pt+ bold)3 : 1
AAANormal text7 : 1
AAALarge text4.5 : 1

These are fixed standard thresholds from the Web Content Accessibility Guidelines, not platform settings, so they are safe to treat as stable facts rather than something to double-check each time.

Why HSL "50% lightness" is not perceptually mid-grey

HSL's lightness is a simple average of the highest and lowest RGB channel — (max + min) ÷ 2 — with no regard for which channels those are. Every fully saturated hue sits at exactly 50% lightness in HSL terms, yet those hues look nothing alike in actual brightness, because HSL's formula and the eye's sensitivity are answering different questions.

Six fully saturated hues, all at HSL lightness 50% — and how differently they actually read
HueHSLRelative luminanceContrast vs blackContrast vs white
Redhsl(0,100%,50%)0.2135.25:14.00:1
Yellowhsl(60,100%,50%)0.92819.56:11.07:1
Greenhsl(120,100%,50%)0.71515.30:11.37:1
Cyanhsl(180,100%,50%)0.78716.75:11.25:1
Bluehsl(240,100%,50%)0.0722.44:18.59:1
Magentahsl(300,100%,50%)0.2856.70:13.14:1

Yellow at "50% lightness" is nearly white in real terms — it fails contrast against a white background almost completely (1.07:1) but reads clearly on black (19.56:1). Blue at the same mathematical lightness is nearly the opposite. If a design system picks text and background colours by matching HSL lightness values, it is not matching perceived brightness at all, and the mismatch above is exactly why a "medium" yellow button with white text so often looks washed out while a "medium" blue one looks fine.

Questions people ask

Why does a value round-trip slightly differently through HSL?

HSL stores hue, saturation and lightness as rounded whole numbers here, matching how CSS and most design tools display them. Converting RGB → HSL → RGB can shift a channel by 1 out of 255 because of that rounding — the colour is visually identical, the numbers just aren't bit-for-bit the same.

Does this support alpha or transparency?

No. HEX, RGB and HSL as implemented here are all fully opaque. Adding an alpha channel changes what "contrast against a background" even means, since a semi-transparent colour's effective contrast depends on whatever sits behind it — that calculation is genuinely a different problem, not an oversight.

Is 3-character HEX like #36C supported?

Yes — it expands to #3366CC automatically, the same way browsers interpret it, by doubling each digit.

Does the colour ever leave my browser?

No. All of the conversion and the contrast maths run in this tab with no server request.

Converting something else?

Units, data storage, time zones and number bases all live right next door.

See all converters →