HEX to RGB Conversion: The Math Behind Color Codes
A step-by-step guide to converting hexadecimal color codes to RGB values, with formulas, examples, and code snippets.
What Are HEX Color Codes?
HEX color codes are one of the most recognizable formats in web development. Written as a hash symbol followed by six hexadecimal characters (for example, #FF6B35), they provide a compact way to specify any of the 16.7 million colors available in the standard RGB color space. The format is #RRGGBB, where each pair of characters represents a single color channel: red, green, and blue.
Hexadecimal is a base-16 number system that uses the digits 0 through 9 and the letters A through F. Each hex digit represents four bits of data, which means a two-digit hex pair can represent values from 00 (0 in decimal) to FF (255 in decimal). This maps perfectly to the 8-bit-per-channel RGB color model used by virtually every screen and browser.
The HEX format was introduced in the earliest days of HTML. Its appeal lies in its brevity: six characters can represent any sRGB color, making it far more compact than the equivalent rgb(255, 107, 53) notation. It remains the most widely used color format in CSS, design tools, and version control diffs.
The Conversion Formula
Converting a HEX color code to RGB is straightforward once you understand the structure. The six-character hex string is split into three pairs, each converted independently from hexadecimal to decimal.
Step-by-Step: Splitting Hex Pairs
Given the color #FF6B35, split it into three two-character pairs:
- Red channel:
FF - Green channel:
6B - Blue channel:
35
Step-by-Step: Parsing to Decimal
Each two-digit hex pair is converted to a decimal number using positional notation. For a hex pair XY, the formula is:
decimal = (X * 16) + Y
where X is the value of the first hex digit
and Y is the value of the second hex digitThe hex digits map to decimal values as follows: 0=0, 1=1, ..., 9=9, A=10, B=11, C=12, D=13, E=14, F=15. Applying this to each channel of #FF6B35:
Worked Example: #FF6B35
FF6B35#FF6B35 = rgb(255, 107, 53)Shorthand HEX Notation
CSS supports a three-character shorthand for hex colors where each digit is repeated. The shorthand #F63 is equivalent to #FF6633. The expansion rule is simple: each character is doubled.
#F63expands to#FF6633#000expands to#000000(black)#FFFexpands to#FFFFFF(white)#09Cexpands to#0099CC
Shorthand notation can only be used when both digits of each pair are identical. You cannot shorten #FF6B35 because the green (6B) and blue (35) channels have different digits. This is why shorthand hex codes are most commonly seen for simple, "round" colors.
Alpha Channel: 8-Digit HEX and RGBA
Modern CSS also supports an 8-digit hex format (#RRGGBBAA) that includes an alpha (transparency) channel. The alpha channel is the fourth pair, with 00 being fully transparent and FF being fully opaque.
For example, #FF6B3580 represents the same orange color with approximately 50% opacity. The alpha value 80 converts to 128 in decimal, which is 128/255 = 0.502, or about 50.2% opacity. The equivalent RGBA notation is rgba(255, 107, 53, 0.502).
The 4-digit shorthand (#RGBA) also exists. For instance, #F638 expands to #FF663388. Browser support for 8-digit and 4-digit hex codes is excellent across all modern browsers, though legacy projects may still need the rgba() fallback.
The RGB Color Space
RGB is an additive color model. This means colors are created by adding light. On a screen, each pixel has three sub-pixels (one red, one green, one blue) that emit light at different intensities. When all three channels are at maximum intensity (255, 255, 255), you see white. When all are at zero (0, 0, 0), you see black.
Each channel spans 0 to 255, giving 256 possible values per channel. With three independent channels, the total number of representable colors is 256 x 256 x 256 = 16,777,216 (approximately 16.7 million). This is the sRGB color gamut, which has been the standard for web content since the mid-1990s.
Understanding the additive model helps predict color mixing. Red (255, 0, 0) plus green (0, 255, 0) produces yellow (255, 255, 0). Red plus blue produces magenta. Green plus blue produces cyan. These secondary colors are the foundation of the color wheel.
Why HEX Exists
The hexadecimal format exists because it provides an efficient representation of the binary data that screens actually use. Each hex digit maps to exactly 4 bits, so a two-digit hex pair maps to exactly 8 bits (one byte). Since each RGB channel is stored as a single byte, the entire color fits neatly into three bytes or six hex characters.
In the early days of HTML, file sizes mattered enormously. Dial-up connections meant every byte counted. The HEX format is significantly more compact than writing rgb(255, 107, 53) (21 characters vs. 7 characters including the hash). This compactness, combined with its ubiquity in early web standards, ensured HEX became the default color format for generations of developers.
Even today, with modern CSS offering more expressive formats like hsl(), oklch(), and named colors, HEX remains the most commonly used format in production code, design tool exports, and brand guidelines.
Code Examples
Here are practical implementations of HEX-to-RGB conversion in popular languages:
// JavaScript
function hexToRgb(hex) {
// Remove the leading # if present
hex = hex.replace(/^#/, '');
// Handle shorthand (#F63 -> FF6633)
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return { r, g, b };
}
hexToRgb('#FF6B35'); // { r: 255, g: 107, b: 53 }
hexToRgb('#F63'); // { r: 255, g: 102, b: 51 }
# Python
def hex_to_rgb(hex_color: str) -> tuple[int, int, int]:
hex_color = hex_color.lstrip('#')
if len(hex_color) == 3:
hex_color = ''.join(c * 2 for c in hex_color)
return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
hex_to_rgb('#FF6B35') # (255, 107, 53)
/* CSS - Both formats are equivalent */
.element {
color: #FF6B35;
color: rgb(255, 107, 53);
/* Modern CSS (space-separated, with optional alpha) */
color: rgb(255 107 53);
color: rgb(255 107 53 / 0.5); /* 50% opacity */
}Reverse Conversion: RGB to HEX
Going the other direction is equally simple. For each decimal channel value (0-255), convert it to a two-digit hex string, then concatenate them:
// JavaScript
function rgbToHex(r, g, b) {
return '#' + [r, g, b]
.map(v => v.toString(16).padStart(2, '0'))
.join('')
.toUpperCase();
}
rgbToHex(255, 107, 53); // "#FF6B35"The padStart(2, '0') ensures values below 16 (which produce single hex digits) are zero-padded: decimal 5 becomes 05, not 5.
Try It Yourself
The best way to solidify your understanding is to experiment. Paste any HEX color into our Color Converter tool and see the instant conversion to RGB, HSL, HWB, OKLCH, and OKLAB. Try short and long hex values, colors with alpha, and watch how each channel maps to its decimal equivalent.
Further Reading
- CSS Color Level 4 specification
The W3C specification defining CSS color values including hex, rgb, and hsl.
- MDN CSS color values
MDN reference for all CSS color value types and conversion rules.
- W3C named colors
Complete list of 148 named CSS colors with their hex and RGB values.