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 0123456789ABCDEF
Decimal Equivalent 0123456789101112131415

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)

  1. Red Channel (3B):
    First digit: 3 (value 3)
    Second digit: B (value 11)
    Calculation: (3 * 16) + 11 = 48 + 11 = 59
  2. Green Channel (82):
    First digit: 8 (value 8)
    Second digit: 2 (value 2)
    Calculation: (8 * 16) + 2 = 128 + 2 = 130
  3. 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)

  1. Red (16):
    16 / 16 = 1 with remainder 0 → Hex pair: 10
  2. Green (185):
    185 / 16 = 11 (which is letter B), with remainder 9 (11 * 16 = 176; 185 - 176 = 9) → Hex pair: B9
  3. Blue (129):
    129 / 16 = 8 with remainder 1 (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);
}