Hex color codes are RGB colors written in base 16. A code like #6366F1 is three two-digit hexadecimal numbers, one each for red, green and blue, and each pair runs from 00 (0) to FF (255). So #6366F1 is exactly rgb(99, 102, 241): the notation changes, the color does not.
How a hex code encodes RGB
Screens build every color from red, green and blue light. CSS stores each of those channels as one byte, an integer from 0 to 255, and a hex code writes the three bytes in a fixed order: #RRGGBB. The leading # tells the CSS parser that hexadecimal digits follow. Hexadecimal uses sixteen symbols, 0 to 9 and then A to F for the values 10 through 15, which is why two digits cover exactly 256 values (16 × 16).
Because each channel has 256 levels, a six-digit code can describe 256 × 256 × 256 = 16,777,216 colors. That is 24-bit color, sometimes called true color, and it is the full range of the sRGB space the web has used since the 1990s. Every one of those colors has exactly one six-digit hex code and exactly one rgb() triplet, so converting between them never loses information. The flip side is that a hex code always means an sRGB color. It cannot express the extra saturation of a Display P3 screen; for that, CSS needs color(display-p3 …) or oklch().
Base-16 math with a worked example
To turn a pair into a decimal number, multiply the first digit by 16 and add the second. Take tomato, #FF6347:
- Red
FF= 15 × 16 + 15 = 255 - Green
63= 6 × 16 + 3 = 99 - Blue
47= 4 × 16 + 7 = 71
The result is rgb(255, 99, 71), which you can confirm on the tomato color page. To go the other way, divide each channel by 16: the whole-number quotient is the first digit and the remainder is the second. A green channel of 144 gives 144 ÷ 16 = 9 remainder 0, so the pair is 90. A red channel of 30 gives 1 remainder 14, or 1E. With blue at 255 (FF) you get #1E90FF, the named color dodgerblue.
You can also read a hex code roughly by eye. The first digit of each pair tells you where that channel sits: 0 to 3 is low, around 8 is the midpoint (0x80 = 128), and C to F is high. Reading #1E90FF that way predicts a strong blue with a fair amount of green and very little red before you see the swatch.
3-, 4-, 6- and 8-digit hex codes
CSS Color Module Level 4 accepts four lengths of hex code:
#RGB: shorthand in which each digit is doubled.#F80expands to#FF8800, orrgb(255, 136, 0).#RGBA: shorthand with an alpha digit.#F808expands to#FF880088.#RRGGBB: the standard form, one byte per channel.#RRGGBBAA: the standard form plus an alpha byte.
A useful shortcut for expanding shorthand: a doubled digit always equals that digit times 17, because hex 11 is 17. So F becomes 15 × 17 = 255 and 8 becomes 8 × 17 = 136, which is how #F80 turns into rgb(255, 136, 0).
Shorthand only works when both digits of every pair match. #6366F1 has no three-digit form, because 63 and F1 are not repeated digits. That restriction limits shorthand to 16 levels per channel, or 4,096 colors in total, which is why design tools almost always export six digits. One neat side effect: all 216 web-safe colors have a shorthand form, since their channels only use 00, 33, 66, 99, CC and FF.
How alpha works in 8-digit hex
The fourth pair is opacity on the same 0 to 255 scale. Divide it by 255 to get the familiar 0 to 1 alpha value. FF is fully opaque, 00 is fully transparent, and 80 is 128 ÷ 255 = 0.502, or about 50%. So #6366F180 matches rgba(99, 102, 241, 0.5) to within rounding. A few more pairs worth memorizing: CC = 204 ÷ 255 = 0.8, 99 = 0.6, 66 = 0.4 and 33 = 0.2.
You cannot hit every round percentage exactly, because 255 does not divide evenly by 100. Fifty percent falls between 7F (127, or 0.498) and 80 (128, or 0.502). The two are visually identical, but if a design token needs an exact value, rgb(99 102 241 / 50%) states the intent more clearly than a hex pair does.
Watch the channel order when you move colors between platforms. CSS puts alpha last (#RRGGBBAA), while Android color resources put it first (#AARRGGBB). The same eight characters describe two different colors on the two platforms, so convert deliberately instead of copying strings across.
Case and other syntax rules
Hex digits are case-insensitive: #ff6347, #FF6347 and #Ff6347 are the same color in CSS, HTML attributes and SVG. Choose one style for a codebase and let a linter enforce it; browsers do not care, but mixed case makes search, replace and code review harder. CSS keywords are case-insensitive too, and the language defines 148 named colors, from rebeccapurple (#663399) to navy (#000080). The full list, with each name's hex code, is on the CSS named colors page.
Common hex color mistakes
- Dropping the hash. Many design apps display hex values without the
#, butcolor: FF6347;is invalid CSS and the browser ignores the whole declaration. - Using the wrong length. Only 3, 4, 6 and 8 digits are valid. A 5- or 7-digit code, usually a copy-paste slip, is ignored, and the element falls back to an inherited or earlier value.
- Treating shorthand and full codes as different colors.
#FFFand#FFFFFFare identical, so a linter can safely normalize one to the other, and a search for one should include the other. - Typing letters beyond F. The letter O in place of the digit 0 is the classic typo, and it silently invalidates the color.
- Mixing up alpha position. A CSS
#RRGGBBAAvalue pasted into an Android resource, or the reverse, swaps a channel for opacity. - Editing digits by hand to lighten or darken. It works for grays, but for colors it shifts saturation and perceived hue unevenly. Generate proper tints and shades instead.
Try it: decode any hex code
Paste a 3-, 4-, 6- or 8-digit code into the HEX to RGB converter to see the decoded channels alongside HSL, HSV, OKLCH and CMYK, each with a copy button. To build a color visually and read its hex code as you drag, use the color picker; it keeps the current color in the URL hash, so /color-picker#ff6347 reopens tomato. For how hex relates to the other notations you will meet in CSS, read RGB vs HSL vs OKLCH.