Colour Love

How hex colour codes work

A six-character hex code is one of the shortest useful strings in tech. Here is exactly what it means, why it looks the way it does, and what every pair of digits is up to.

A hex colour code looks like #FF5733. Six characters, maybe a hash in front, maybe not. Almost every colour you see on a screen, on this page, in your OS, in your favourite app, is stored and transmitted as some version of this six-character string.

It is a compact little format. It is also one of the most misunderstood things in front-end development, because almost nobody is taught what the six digits are doing. Here is the whole thing.

The six digits are three pairs

A hex code is three pairs of two hexadecimal digits. Read left to right:

  • The first pair is the amount of red.
  • The second pair is the amount of green.
  • The third pair is the amount of blue.

#FF5733 means: lots of red (FF), a bit of green (57), a medium pinch of blue (33).

Each pair answers the same question: on a scale from zero to maximum, how much of this colour do we want? The answer is a two-digit hexadecimal number.

#FF5733 decomposed Each bar shows a channel's 0–255 value. R · FF · 255 G · 57 · 87 B · 33 · 51 resulting colour
Hex reads left to right as three one-byte channels. #FF5733 = R 255, G 87, B 51.

Hexadecimal, briefly

Humans count in base 10. Computers count in base 2 (binary). Hex is base 16, a compromise that packs binary neatly for humans to read.

Hex digits go 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. A is 10, B is 11, and so on up to F, which is 15. Two hex digits can represent any number from 00 (zero) to FF (255). That is exactly one byte.

So each colour channel, red, green, blue, gets one byte. Zero is none of that colour, 255 is all of it.

FF is 255. 57 is 87. 33 is 51. So #FF5733 is red 255, green 87, blue 51. In CSS you could write the same colour as rgb(255, 87, 51) and the browser would not care which notation you used.

Why 255 is the ceiling

The ceiling is 255 because a single byte has eight bits, and eight bits can count from 0 to 255. That is just the shape of a byte. The choice of one byte per channel is a design decision by the people who specified how computers should represent colour. It is not the only possible choice, and most high-end displays today actually use ten or twelve bits per channel internally. But the web, for historical reasons, settled on eight bits per channel, which gives hex its six-character form.

Three channels of eight bits each is 24 bits total. Two to the power of 24 is 16,777,216. That is the total number of colours a hex code can describe. It is also the number in our homepage headline, and it is not a round number for any reason other than that the maths works out that way.

Red, green, blue, why those three

The short answer is that human eyes have three kinds of cone cells, each tuned to a different range of wavelengths, and those ranges centre roughly on red, green, and blue light. Mix the three and you can fool the eye into seeing any perceivable colour. Screens exploit this shamelessly. Each pixel on your display is three tiny lights, red, green, blue, and the hex code is the recipe for how bright to make each one.

This is also why hex colour is called an additive colour model. You start with black (all channels zero) and add light to get other colours. Mix all three at full blast, #FFFFFF, and you get white. Mix none of them, #000000, and you get black, because black is the absence of light.

Print works the other way. Print starts from white paper and subtracts light by adding ink. That is why print uses CMYK, not RGB. A different article, another day.

Three-character hex is not a different format

You will sometimes see #F53 instead of #FF5533. This is a shorthand. Each single digit in the three-character form expands by duplicating itself.

  • #F53#FF5533
  • #0AF#00AAFF
  • #FFF#FFFFFF

This shortcut can only describe 4,096 colours (16 × 16 × 16), not 16,777,216, because each channel is constrained to one of 16 values instead of 256. For most design work this is plenty. For subtle gradients, branded colours, or anything where accuracy matters, use the full six-character form.

The hash is optional in some places and required in others

In CSS you must include the #. color: #FF5733 works. color: FF5733 does not, CSS treats unprefixed hex as either invalid or as the start of an identifier.

In most design tools, code editors, and colour pickers, the hash is optional. In hex-to-RGB converters it is cosmetic. In URL slugs, file names, and database columns, the hash is usually dropped entirely.

Our own URLs are a case in point. colour.love/adopt/FF5733 works. colour.love/adopt/%23FF5733 would technically also work, but nobody wants to URL-encode a hash. The hash is a convention, not a part of the number.

Alpha, the optional fourth pair

Modern CSS lets you extend the hex code with a fourth pair to specify transparency. #FF573380 is #FF5733 at 50% opacity, because 80 in hex is 128 in decimal, which is halfway between 0 (transparent) and 255 (opaque).

This is called eight-character hex, or hex-with-alpha, or RGBA-hex depending who you ask. It is widely supported in browsers since around 2018. The short form works here too, #F538 expands to #FF553388.

Design tools vary in their handling. Figma accepts eight-character hex. Photoshop does not, it separates the alpha into its own percentage field. Tailwind supports it via the bg-[#FF573380] bracket notation. Use it when you want to write transparency directly into a single value instead of using rgba().

Hex is not always the right answer

Hex is compact, portable, and widely understood. It is also completely unintuitive as a way to reason about colour. Ask yourself: if I want a slightly darker version of #FF5733, what do I change? The answer is “lower all three channels by similar amounts,” which is neither obvious nor precise.

Other notations are better at this. HSL lets you say “make it 10% darker” by changing the lightness value directly. OKLCH is even better because it uses a model that matches how human eyes actually perceive brightness. For serious design-system work, most teams now author in HSL or OKLCH and convert to hex only when the browser or API demands it.

A separate article in this series goes into when to use which. For most day-to-day colour work, hex is fine, and understanding the six digits is enough to make it feel less like magic and more like the tidy little byte-shaped thing it actually is.

Read it as a number

If you remember nothing else: #FF5733 is just three numbers mashed together. Red: 255. Green: 87. Blue: 51. Zero to 255. Base 16 for brevity. That is the whole story. Every hex code you encounter, in every file, every stylesheet, every adoption page on this site, is doing exactly the same thing. It is a compact recipe for three tiny lights.

Now that you know what the numbers mean, you will start seeing patterns in them. #FF0000 is pure red. #00FF00 is pure green. #808080 is mid grey. #1A1A1A is almost-black. After a while you can read a hex code the way a musician reads a chord: at a glance, a whole feeling.

Frequently asked questions

What does a hex colour code actually mean?
A hex code is three pairs of hexadecimal digits after a #. Each pair is one byte, red, green, blue, from 00 (none) to FF (max, 255). #FF5733 is red 255, green 87, blue 51.
Why do hex codes have six characters?
Because each of the three colour channels (red, green, blue) uses 8 bits, and two hex digits can exactly represent one 8-bit byte. Three bytes × two hex digits each = six characters.
Is the hash (#) required?
In CSS, yes. In most design tools, file names, URLs, and converters, it is optional. The hash is a convention used to mark the string as a hex colour, it is not part of the number itself.
What does three-character hex like #F53 mean?
It is a shorthand. Each digit doubles: #F53 expands to #FF5533. It can only describe 4,096 colours instead of 16,777,216, so it is fine for quick work but imprecise for design systems.
What does the fourth pair in #FF573380 do?
It sets alpha (transparency). 00 is fully transparent, FF is fully opaque, 80 is roughly 50%. Eight-character hex has been supported in all modern browsers since around 2018.
Should I author my design system in hex?
No. Hex is a transmission format, not a design format. Author in OKLCH (or HSL if unavailable) and serialize to hex for storage and CSS output. Hex has no dimensions you can reason about, lightness, saturation, hue are all tangled together.

Defined terms

Hex code
A compact textual representation of an RGB colour using base-16 digits. Six characters for opaque colour (#RRGGBB), eight with alpha (#RRGGBBAA).
Byte
Eight bits of data. Can represent 256 distinct values, from 0 to 255. Each hex pair encodes exactly one byte.
Hexadecimal
A base-16 number system using digits 0–9 and letters A–F. A–F represent decimal 10–15. Two hex digits encode values 0–255 in a compact form.
Additive colour
A colour model where colours are formed by mixing light. Zero of everything is black; full intensity of all channels is white. Screens use additive colour.
Alpha channel
An additional channel encoding transparency. 00 is fully transparent, FF is fully opaque. Added to hex as a trailing pair: #RRGGBBAA.
sRGB
The default colour space of the web, specified in 1996. Defines which physical colours the 24-bit codes correspond to.

More articles