HEX, RGB and HSL: understanding colour codes

Three notations for the same colours — and when each one earns its keep.

Open any stylesheet and you’ll meet the same colour written three different ways: #3366ff, rgb(51, 102, 255) and hsl(225, 100%, 60%). They all paint the exact same pixel. What changes is how the number is built — and once you understand the structure of each one, you can read a colour off the screen, tweak it by hand, and build a palette without guessing. Let’s take them in turn.

HEX: red, green and blue in base 16

A HEX code is a screen colour written as red, green and blue channels in hexadecimal (base 16). The canonical form is #RRGGBB: two hex digits each for red, green and blue. Each pair runs from 00 to FF, which is 0 to 255 in everyday decimal. So #000000 is pure black (all channels off), #FFFFFF is white (all channels at full), and #FF0000 is full-strength red with no green or blue.

Two shorthands are worth knowing. #RGB is a three-digit form where each digit is doubled — #39F expands to #3399FF — handy when every channel happens to use a repeated digit. And #RRGGBBAA adds a fourth pair for alpha (opacity): #3366FF80 is that blue at roughly 50% opacity, because 80 in hex is 128, about halfway to 255.

RGB: the same channels, in plain decimal

rgb(r, g, b) describes exactly the same three channels as HEX, just written in decimal from 0 to 255 instead of hex pairs. #3366FF and rgb(51, 102, 255) are the identical colour — 33 hex is 51, 66 hex is 102, and FF hex is 255. The decimal form is easier to reason about arithmetically, which is why code that mixes or interpolates colours usually works in RGB.

To add opacity you use rgba(r, g, b, a), where the alpha is a fraction from 0 (fully transparent) to 1 (fully opaque): rgba(51, 102, 255, 0.5). Modern CSS also lets you write the alpha directly inside rgb() with a slash — rgb(51 102 255 / 50%) — so the separate rgba() keyword is no longer strictly necessary.

HSL: the one built for humans

HSL describes a colour the way a person thinks about one. Instead of three light channels, it uses hue, saturation and lightness:

Hue — 0 to 360°

The position on the colour wheel, in degrees. Red sits at 0°, green at 120°, blue at 240°, and it wraps back to red at 360°.

Saturation — 0 to 100%

How vivid the colour is. 0% is a flat grey; 100% is the purest, most intense version of that hue.

Lightness — 0 to 100%

How light or dark it is. 0% is always black, 100% is always white, and 50% is the “full” colour.

This split is why HSL is so pleasant for editing. Want the same colour but darker? Drop the lightness and leave hue and saturation alone. Need a warmer variant? Nudge the hue a few degrees. Building a palette of related colours is just a matter of holding saturation and lightness steady while rotating the hue — something that is fiddly and error-prone in HEX or RGB, where every shift touches all three numbers at once.

How they convert

HEX and RGB are trivially interchangeable: each HEX pair is simply a channel value written in base 16, so converting is just changing the number base. CC in hex is 12 × 16 + 12 = 204 in decimal, and 204 back to hex is CC. HSL is a genuine transformation rather than a re-spelling — the conversion maps the red/green/blue cube onto a cylinder of hue, saturation and lightness — but it is exact and loss-free in both directions for opaque colours. The table below shows one colour in all three.

NotationValueWhat each part means
HEX#3366FFR=33, G=66, B=FF (hex pairs)
RGBrgb(51, 102, 255)R=51, G=102, B=255 (0–255)
HSLhsl(225, 100%, 60%)hue 225°, fully saturated, 60% light

You rarely need to do this by hand. Paste any of the three formats into the colour converter and palette builder and it shows you the other notations instantly, plus harmonious palettes built around your colour. It runs entirely in your browser.

Alpha, opacity and why contrast matters

Alpha controls transparency rather than colour: it decides how much of whatever sits behind an element shows through. A button at rgba(0, 0, 0, 0.6) looks different over a white card than over a photo, because the final colour is a blend. That blend is also why semi-transparent text is risky — its effective contrast depends on the background it lands on.

Contrast is the difference in brightness between text and its background, expressed as a ratio from 1:1 (identical, invisible) to 21:1 (pure black on pure white). The Web Content Accessibility Guidelines set thresholds that good designs should meet:

LevelNormal textLarge text (≈18.7px bold or 24px+)
WCAG AA4.5:13:1
WCAG AAA7:14.5:1

A pairing can look fine to you and still fail — light grey on white is a classic offender — which is why the ratio is worth measuring rather than eyeballing. Drop your foreground and background colours into the contrast checker to see the live ratio and whether it clears AA or AAA before you ship.

Reading or building colours? Start with the colour converter & palette builder — paste a HEX, RGB or HSL value and get the other two formats plus ready-made palettes, all computed locally in your browser.

Related tools: Colour tools · Contrast checker