Why Understand Color Math?
Every developer has color pickers and browser DevTools at their fingertips. Why take five minutes to understand how hexadecimal colors convert to RGB decimal numbers by hand?
Because demystifying base-16 notation transforms cryptic codes like #3B82F6 from arbitrary strings into predictable data. You will be able to inspect code diffs and instantly recognize that #F3F4F6 is a light gray, #1E293B is a dark navy, and #EF4444 is an energetic red, without opening an inspector.
The Basics: What Does "Hexadecimal" Mean?
We count daily in decimal (base 10) using ten symbols: 0 through 9. When we reach ten, we roll over into two digits (10).
Hexadecimal (base 16) uses sixteen symbols. To represent numbers from 10 to 15 with a single character, it uses letters A through F:
| Hex Digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Decimal Equivalent | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
In a standard 6-digit hex code #RRGGBB, the 6 characters break down into three 2-digit hex pairs: Red, Green, and Blue.
The Conversion Formula: HEX to RGB
To convert any 2-digit hex pair into a decimal number from 0 to 255, multiply the first digit by 16 and add the second digit:
Decimal Value = (First Digit * 16) + Second Digit
Worked Example 1: Converting Tailwind Blue (#3B82F6)
- Red Channel (
3B):
First digit:3(value 3)
Second digit:B(value 11)
Calculation:(3 * 16) + 11 = 48 + 11 = 59 - Green Channel (
82):
First digit:8(value 8)
Second digit:2(value 2)
Calculation:(8 * 16) + 2 = 128 + 2 = 130 - Blue Channel (
F6):
First digit:F(value 15)
Second digit:6(value 6)
Calculation:(15 * 16) + 6 = 240 + 6 = 246
Result: #3B82F6 becomes rgb(59, 130, 246)!
The Reverse Formula: RGB to HEX
To convert a decimal value (0 to 255) back to a 2-digit hex pair, use integer division and modulo (remainder) by 16:
- First Digit:
Math.floor(value / 16) - Second Digit:
value % 16
Worked Example 2: Converting Emerald Green rgb(16, 185, 129)
- Red (16):
16 / 16 = 1with remainder0→ Hex pair:10 - Green (185):
185 / 16 = 11(which is letterB), with remainder9(11 * 16 = 176; 185 - 176 = 9) → Hex pair:B9 - Blue (129):
129 / 16 = 8with remainder1(8 * 16 = 128; 129 - 128 = 1) → Hex pair:81
Result: rgb(16, 185, 129) becomes #10B981!
Shorthand HEX: The 3-Digit Trick
In CSS, whenever both digits in a channel pair are identical, the code can be shortened to 3 characters: #RGB.
Crucially, #123 does NOT expand to #102030; it duplicates each digit: #112233. That's why pure white #FFFFFF shortens to #FFF, and solid black #000000 shortens to #000.
Production JavaScript Converter Functions
// Convert HEX to RGB Object
function hexToRgb(hex) {
// Strip leading hash
hex = hex.replace(/^#/, '');
// Expand shorthand (e.g. "03F") to full form ("0033FF")
if (hex.length === 3) {
hex = hex.split('').map(char => char + char).join('');
}
const num = parseInt(hex, 16);
return {
r: (num >> 16) & 255,
g: (num >> 8) & 255,
b: num & 255
};
}
// Convert RGB to HEX String
function rgbToHex(r, g, b) {
const toHex = (n) => Math.max(0, Math.min(255, Math.round(n)))
.toString(16)
.padStart(2, '0');
return '#' + toHex(r) + toHex(g) + toHex(b);
}