HTML Color Codes: Hex, RGB, HSL, and Named Colors Explained
Every pixel on a web page has a color, and every color has a code. HTML and CSS support four main color formats — hex, RGB, HSL, and named colors — and choosing the wrong one for the job makes your stylesheet harder to read and maintain.
This guide explains all four formats, when to use each, how to convert between them with code, and how to check whether your color combinations are accessible.
The Four HTML Color Formats
1. Hex (#RRGGBB)
The most common format on the web. Each pair of hexadecimal digits represents a channel (red, green, blue) from 00 (0) to FF (255).
color: #3a86ff; /* vivid blue */
background: #ff006e; /* hot pink */
border-color: #000000; /* black */
3-digit shorthand — when both digits in each pair are the same, you can shorten:
#ff0000 → #f00 /* red */
#ffffff → #fff /* white */
#aabbcc → #abc
8-digit RGBA hex (modern browsers) — adds an alpha channel:
background: #3a86ffcc; /* blue at 80% opacity */
2. RGB / RGBA
RGB writes the same three channels as decimal integers (0–255). RGBA adds a fourth value for opacity (0.0–1.0):
color: rgb(58, 134, 255);
background: rgba(58, 134, 255, 0.5); /* 50% opacity */
CSS Color Level 4 also allows the newer space-separated syntax without commas:
color: rgb(58 134 255);
color: rgb(58 134 255 / 50%);
3. HSL / HSLA
HSL — Hue, Saturation, Lightness — is the most human-friendly format:
- Hue (0–360): angle on the colour wheel (0 = red, 120 = green, 240 = blue)
- Saturation (0–100%): 0% = grey, 100% = full colour
- Lightness (0–100%): 0% = black, 50% = normal, 100% = white
color: hsl(217, 100%, 61%); /* same vivid blue as #3a86ff */
background: hsla(217, 100%, 61%, 0.5); /* 50% opacity */
HSL shines when you want to create colour palettes programmatically — increment the hue to get analogous colours, adjust lightness to get tints and shades.
4. Named Colors
CSS defines 148 named colors, from the simple (red, blue, white) to the obscure (rebeccapurple, papayawhip, cornsilk). They are useful for prototyping but too imprecise for production design:
color: tomato;
background: steelblue;
border: 2px solid goldenrod;
The special keyword transparent is equivalent to rgba(0, 0, 0, 0).
Quick Reference: All Four Formats Side by Side
| Format | Example | Alpha? | Best for |
|---|---|---|---|
| Hex | #3a86ff |
#3a86ffcc |
Design specs, copy-paste from Figma |
| RGB | rgb(58, 134, 255) |
rgba(…, 0.5) |
Canvas API, image processing |
| HSL | hsl(217, 100%, 61%) |
hsla(…, 0.5) |
Generating palettes, theming |
| Named | royalblue |
— | Quick prototyping only |
All four are valid in any CSS property that accepts a color value.
Converting Between Formats
Hex → RGB (JavaScript)
function hexToRgb(hex) {
// Remove # and expand 3-digit to 6-digit
hex = hex.replace(/^#/, '');
if (hex.length === 3) {
hex = hex.split('').map(c => c + c).join('');
}
const n = parseInt(hex, 16);
return {
r: (n >> 16) & 255,
g: (n >> 8) & 255,
b: n & 255,
};
}
hexToRgb('#3a86ff'); // { r: 58, g: 134, b: 255 }
RGB → Hex (JavaScript)
function rgbToHex(r, g, b) {
return '#' + [r, g, b]
.map(v => v.toString(16).padStart(2, '0'))
.join('');
}
rgbToHex(58, 134, 255); // '#3a86ff'
RGB → HSL (Python)
import colorsys
def rgb_to_hsl(r, g, b):
# colorsys works in 0–1 range
h, l, s = colorsys.rgb_to_hls(r / 255, g / 255, b / 255)
return round(h * 360), round(s * 100), round(l * 100)
rgb_to_hsl(58, 134, 255) # (217, 100, 61)
Hex → RGB (Go)
package main
import (
"fmt"
"strconv"
"strings"
)
func hexToRGB(hex string) (r, g, b uint8) {
hex = strings.TrimPrefix(hex, "#")
n, _ := strconv.ParseUint(hex, 16, 32)
return uint8(n >> 16), uint8(n >> 8 & 0xFF), uint8(n & 0xFF)
}
func main() {
r, g, b := hexToRGB("#3a86ff")
fmt.Printf("rgb(%d, %d, %d)\n", r, g, b) // rgb(58, 134, 255)
}
Hex → RGB (PHP)
function hexToRgb(string $hex): array {
$hex = ltrim($hex, '#');
if (strlen($hex) === 3) {
$hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
}
return [
'r' => hexdec(substr($hex, 0, 2)),
'g' => hexdec(substr($hex, 2, 2)),
'b' => hexdec(substr($hex, 4, 2)),
];
}
print_r(hexToRgb('#3a86ff')); // ['r' => 58, 'g' => 134, 'b' => 255]
Colour Contrast and Accessibility (WCAG)
Picking a colour is only half the job. If the text and background don't have enough contrast, people with low vision (or anyone in bright sunlight) can't read it.
WCAG 2.1 contrast ratio requirements:
| Level | Normal text | Large text (18pt / 14pt bold) |
|---|---|---|
| AA | 4.5 : 1 | 3 : 1 |
| AAA | 7 : 1 | 4.5 : 1 |
Contrast ratio is calculated from relative luminance — a weighted formula based on the linear RGB values:
L = 0.2126 R + 0.7152 G + 0.0722 B
ratio = (L_lighter + 0.05) / (L_darker + 0.05)
JavaScript — compute contrast ratio:
function luminance(r, g, b) {
const [rv, gv, bv] = [r, g, b].map(v => {
v /= 255;
return v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;
});
return 0.2126 * rv + 0.7152 * gv + 0.0722 * bv;
}
function contrastRatio(hex1, hex2) {
const [c1, c2] = [hex1, hex2].map(h => {
const n = parseInt(h.replace('#', ''), 16);
return luminance(n >> 16, (n >> 8) & 255, n & 255);
});
const [l, d] = c1 > c2 ? [c1, c2] : [c2, c1];
return ((l + 0.05) / (d + 0.05)).toFixed(2);
}
contrastRatio('#3a86ff', '#ffffff'); // '3.07' — fails AA for normal text
contrastRatio('#1a56db', '#ffffff'); // '4.65' — passes AA
Always check contrast before shipping — blue on white often looks fine at full screen size but fails when the font is small.
Choosing the Right Format
Use hex when you're copying colours from a design tool (Figma, Adobe XD, Sketch) or writing static CSS where you won't touch the values again.
Use RGB when you're manipulating colours in JavaScript (canvas, WebGL, OffscreenCanvas) or in any image-processing library — they all speak integers.
Use HSL when you're generating a palette or building a theme. Changing lightness from 50% to 80% gives a pastel tint; changing hue by 30° gives an analogous colour. Far easier than calculating the equivalent hex arithmetic.
Avoid named colors in production. steelblue is exactly rgb(70, 130, 180) — but three months later you won't remember that, and neither will the next developer.
Common Mistakes
| Mistake | Why it breaks | Fix |
|---|---|---|
#RGB instead of #RRGGBB |
#abc is valid but only where each digit doubles (#aabbcc); #a1b is not valid shorthand |
Always write 6 digits when channels differ |
rgba(r, g, b, 255) |
Alpha in CSS rgba() is 0–1, not 0–255 | Use rgba(r, g, b, 1.0) for opaque |
| Forgetting to clamp | After arithmetic, RGB channels can go below 0 or above 255 | Math.min(255, Math.max(0, value)) |
| HSL hue wrapping | Hue is circular — after 360 it wraps to 0 | Apply ((h % 360) + 360) % 360 |
| Hex case mismatch | #3A86FF and #3a86ff are identical; case doesn't matter in CSS |
Lowercase convention is more common |
parseFloat on hex |
parseInt('#3a86ff', 16) fails due to #; must strip it first |
parseInt(hex.replace('#',''), 16) |
Frequently Asked Questions
What is the most common HTML color format?
Hex (#RRGGBB) is the most widely used format in CSS stylesheets. It originated from early browser implementations and remains dominant because design tools output it by default.
Can I mix hex and RGB in the same stylesheet?
Yes, every CSS property that accepts a color value accepts any valid format. You can use color: #3a86ff and background: rgb(58, 134, 255) in the same rule without issues.
What does the alpha channel actually mean?
Alpha controls opacity: 0 (or rgba(…, 0)) is fully transparent; 1 (or rgba(…, 1)) is fully opaque. Values in between create semi-transparent effects. The 8-digit hex equivalent maps 0–255 to 00–FF.
Why does blue text on a white background fail WCAG contrast?
Bright blues like #3a86ff have a luminance high enough to look visible but low enough to fail 4.5:1 against white. Darken the blue (lower the lightness in HSL) until the contrast ratio passes.
Is #000000 the same as black?
Yes, exactly. #000000, rgb(0,0,0), hsl(0,0%,0%), and black all produce the same pixel. Similarly #ffffff = white.
Which format does CSS currentColor use?
currentColor is not a format — it's a keyword that inherits the element's color property, whatever format that was set in. The browser resolves it at paint time.