CSS Colors: HEX, RGB, HSL Explained — When to Use Each Format
A visual guide to CSS color formats — HEX, RGB, HSL, and modern CSS color functions. Learn when to use each format, how to convert between them, and tips for building accessible color palettes.
CSS Color Formats Overview
CSS supports multiple ways to define colors. Each format has its strengths, and understanding when to use each one will make your CSS more readable and maintainable.
HEX Colors
HEX (hexadecimal) is the most common color format in CSS. It represents colors using a # followed by 6 hex digits (or 3 for shorthand):
color: #6366f1; /* Full hex */
color: #fff; /* Shorthand for #ffffff */
color: #6366f180; /* With alpha (50% opacity) */
How HEX Works
Each pair of digits represents a color channel (Red, Green, Blue), with values from 00 (0) to FF (255):
#6366f1
^^ ^^ ^^
R G B
99 102 241
Shorthand
When each pair has identical digits, you can use 3-digit shorthand:
#ffffff → #fff
#000000 → #000
#ff6600 → #f60
#aabbcc → #abc
When to Use HEX
- Design handoffs (Figma, Sketch export HEX by default)
- When you have a specific brand color code
- Quick one-off color definitions
- When you don't need to manipulate the color programmatically
RGB and RGBA
RGB defines colors using Red, Green, and Blue channel values from 0 to 255:
/* Modern syntax (recommended) */
color: rgb(99 102 241);
color: rgb(99 102 241 / 50%);
/* Legacy syntax (still works) */
color: rgb(99, 102, 241);
color: rgba(99, 102, 241, 0.5);
When to Use RGB
- When you need to calculate colors programmatically
- When working with JavaScript (canvas, animations)
- When you need alpha transparency
- When color values come from a database or API
RGB in JavaScript
// Parse RGB from a string
const [r, g, b] = "rgb(99, 102, 241)".match(/\d+/g).map(Number);
// Generate random color
const randomColor = `rgb(${Math.random()*255|0} ${Math.random()*255|0} ${Math.random()*255|0})`;
// Darken a color by 20%
const darken = (r, g, b, amount) =>
`rgb(${r*(1-amount)|0} ${g*(1-amount)|0} ${b*(1-amount)|0})`;
HSL and HSLA
HSL defines colors using Hue, Saturation, and Lightness — which maps more closely to how humans think about color:
/* Modern syntax */
color: hsl(239 84% 67%);
color: hsl(239 84% 67% / 50%);
/* Legacy syntax */
color: hsl(239, 84%, 67%);
color: hsla(239, 84%, 67%, 0.5);
Understanding HSL
-
Hue (0-360) — The color on the color wheel
- 0° = Red
- 60° = Yellow
- 120° = Green
- 180° = Cyan
- 240° = Blue
- 300° = Magenta
-
Saturation (0-100%) — Color intensity
- 0% = Gray (no color)
- 100% = Full color
-
Lightness (0-100%) — How light or dark
- 0% = Black
- 50% = Normal
- 100% = White
Why HSL is Powerful
HSL makes it trivial to create color variations:
:root {
--brand-hue: 239;
--brand-sat: 84%;
/* Generate a full palette from one hue */
--brand-50: hsl(var(--brand-hue) var(--brand-sat) 97%);
--brand-100: hsl(var(--brand-hue) var(--brand-sat) 93%);
--brand-200: hsl(var(--brand-hue) var(--brand-sat) 85%);
--brand-300: hsl(var(--brand-hue) var(--brand-sat) 75%);
--brand-400: hsl(var(--brand-hue) var(--brand-sat) 67%);
--brand-500: hsl(var(--brand-hue) var(--brand-sat) 55%);
--brand-600: hsl(var(--brand-hue) var(--brand-sat) 45%);
--brand-700: hsl(var(--brand-hue) var(--brand-sat) 35%);
--brand-800: hsl(var(--brand-hue) var(--brand-sat) 25%);
--brand-900: hsl(var(--brand-hue) var(--brand-sat) 15%);
}
To create a hover state, just adjust lightness:
.button {
background: hsl(239 84% 55%);
}
.button:hover {
background: hsl(239 84% 45%); /* 10% darker */
}
When to Use HSL
- Building color systems and design tokens
- Creating color palettes programmatically
- Hover/active state variations
- Dark mode implementations
- When you need intuitive color manipulation
Converting Between Formats
HEX to RGB
function hexToRgb(hex) {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return { r, g, b };
}
RGB to HSL
function rgbToHsl(r, g, b) {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const l = (max + min) / 2;
let h = 0, s = 0;
if (max !== min) {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
case g: h = ((b - r) / d + 2) / 6; break;
case b: h = ((r - g) / d + 4) / 6; break;
}
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
l: Math.round(l * 100)
};
}
Accessibility and Color Contrast
The WCAG (Web Content Accessibility Guidelines) requires minimum contrast ratios:
- Normal text: 4.5:1 contrast ratio (AA) or 7:1 (AAA)
- Large text (18px+ bold or 24px+): 3:1 (AA) or 4.5:1 (AAA)
// Calculate relative luminance
function luminance(r, g, b) {
const [rs, gs, bs] = [r, g, b].map(c => {
c /= 255;
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
});
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
}
// Calculate contrast ratio
function contrastRatio(rgb1, rgb2) {
const l1 = luminance(...rgb1);
const l2 = luminance(...rgb2);
const lighter = Math.max(l1, l2);
const darker = Math.min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
Tips for Choosing Colors
- Use HSL for your design system — It makes creating consistent palettes effortless
- Test contrast ratios — Use tools to ensure text is readable
- Don't rely on color alone — Use icons, patterns, or text labels alongside color indicators
- Consider color blindness — About 8% of men have some form of color vision deficiency
- Use CSS custom properties — Define colors once, use everywhere
Convert between color formats instantly with our Color Converter and Color Picker tools.