HEX, RGB, HSL: Understanding Color Formats for Web Design
If you’ve ever written CSS, you’ve typed a color value. Maybe it was a HEX code like #FF5733, an RGB value like rgb(255, 87, 51), or an HSL value like hsl(9, 100%, 60%). These all describe the exact same color — but they use very different approaches.
Understanding the differences between these formats isn’t just academic trivia. It affects how efficiently you work, how easily you create color systems, and how accessible your designs are. This guide covers everything you need to know about color formats in web design.
The Three Main Color Formats
HEX (Hexadecimal)
HEX is the most widely used color format in web design. It expresses colors as a six-character hexadecimal string, where each pair of characters represents the intensity of red, green, and blue.
Format: #RRGGBB
Example: #FF5733
FF= Red (255 in decimal)57= Green (87 in decimal)33= Blue (51 in decimal)
Shorthand: When both characters in a pair are the same, you can abbreviate:
#FF5733→ cannot be shortened#3366FF→#36F#AABBCC→#ABC
Pros:
- Compact and easy to copy/paste
- Universally supported
- Most design tools default to HEX
Cons:
- Not intuitive — hard to tell what color
#8B4513is by looking at it - Difficult to adjust programmatically (lighten, darken, shift hue)
- No built-in alpha channel in the 6-digit format (though 8-digit HEX exists)
RGB (Red, Green, Blue)
RGB expresses colors as three numeric values from 0 to 255, representing the intensity of each primary color.
Format: rgb(red, green, blue)
Example: rgb(255, 87, 51) is the same as #FF5733
RGBA (with alpha): rgba(255, 87, 51, 0.5) — the fourth value is opacity from 0 (transparent) to 1 (opaque)
Modern syntax: CSS now supports rgb(255 87 51 / 0.5) with space-separated values and a slash before alpha.
Pros:
- More readable than HEX — you can see individual channel values
- Native alpha channel support
- Easy to understand: 0 = off, 255 = full intensity
Cons:
- Still not intuitive for color manipulation
- Hard to predict what happens when you change one value
- Verbose compared to HEX
HSL (Hue, Saturation, Lightness)
HSL describes colors in terms that match how humans perceive them: what color it is (hue), how vivid it is (saturation), and how bright it is (lightness).
Format: hsl(hue, saturation%, lightness%)
- Hue: 0–360 degrees on the color wheel (0 = red, 120 = green, 240 = blue)
- Saturation: 0% (gray) to 100% (full color)
- Lightness: 0% (black) to 100% (white), 50% = pure color
Example: hsl(9, 100%, 60%) is the same as #FF5733
HSLA (with alpha): hsla(9, 100%, 60%, 0.5)
Modern syntax: hsl(9 100% 60% / 0.5)
Pros:
- Most intuitive for humans — you can reason about colors
- Easy to create variations: change lightness for shades, change saturation for vibrancy
- Perfect for building color systems and palettes
- Simple to create accessible color schemes
Cons:
- Less commonly used in design tool output
- Slightly more verbose
- Hue values can be confusing until you memorize the color wheel
When to Use Which Format
Use HEX When:
- Copying colors from design tools (Figma, Sketch, etc.)
- Writing quick one-off color values
- Working with existing codebases that use HEX
- You need maximum brevity
Use RGB When:
- You need alpha transparency
- You’re working with canvas or WebGL APIs
- You’re reading pixel data from images
- You need to manipulate individual color channels programmatically
Use HSL When:
- Building a design system with color scales
- Creating hover/active/disabled states from a base color
- Implementing dark mode (adjust lightness)
- You need to ensure accessible contrast ratios
- Generating colors programmatically
Practical CSS Examples
Building a Color System with HSL
:root {
/* Base hue for the brand */
--hue-primary: 220;
/* Full palette generated from one hue */
--color-primary-50: hsl(var(--hue-primary), 100%, 97%);
--color-primary-100: hsl(var(--hue-primary), 95%, 90%);
--color-primary-200: hsl(var(--hue-primary), 90%, 80%);
--color-primary-300: hsl(var(--hue-primary), 85%, 65%);
--color-primary-400: hsl(var(--hue-primary), 80%, 55%);
--color-primary-500: hsl(var(--hue-primary), 75%, 50%);
--color-primary-600: hsl(var(--hue-primary), 80%, 40%);
--color-primary-700: hsl(var(--hue-primary), 85%, 30%);
--color-primary-800: hsl(var(--hue-primary), 90%, 20%);
--color-primary-900: hsl(var(--hue-primary), 95%, 12%);
}
This approach lets you change the entire brand color by updating a single --hue-primary value.
Interactive Hover States
.button {
background-color: hsl(200, 80%, 50%);
transition: background-color 0.2s;
}
.button:hover {
/* Slightly darker on hover — just change lightness */
background-color: hsl(200, 80%, 40%);
}
.button:disabled {
/* Desaturated and lighter for disabled state */
background-color: hsl(200, 20%, 70%);
}
Alpha Transparency
/* Modern CSS syntax */
.overlay {
background-color: rgb(0 0 0 / 0.5); /* 50% transparent black */
}
.card {
background-color: hsl(200 80% 50% / 0.1); /* Very subtle blue tint */
border: 1px solid hsl(200 80% 50% / 0.3); /* Matching border */
}
The Alpha Channel
All three formats support transparency through the alpha channel:
| Format | Syntax | Alpha Range |
|---|---|---|
| HEX (8-digit) | #RRGGBBAA | 00–FF (0–255) |
| RGBA | rgba(r, g, b, a) | 0–1 |
| HSLA | hsla(h, s%, l%, a) | 0–1 |
HEX alpha examples:
#FF573380— 50% opacity (80 in hex = 128 in decimal = ~0.5)#FF573300— fully transparent#FF5733FF— fully opaque
Common alpha values in HEX:
| Opacity | HEX Suffix |
|---|---|
| 100% | FF |
| 75% | BF |
| 50% | 80 |
| 25% | 40 |
| 10% | 1A |
| 0% | 00 |
Converting Between Formats
HEX to RGB
Split the HEX code into three pairs and convert each from hexadecimal to decimal:
#FF5733 → FF = 255, 57 = 87, 33 = 51 → rgb(255, 87, 51)
RGB to HEX
Convert each decimal value to hexadecimal and concatenate:
rgb(255, 87, 51) → 255 = FF, 87 = 57, 51 = 33 → #FF5733
RGB to HSL
This requires a few steps:
- Divide each RGB value by 255 to get values from 0 to 1
- Find the maximum and minimum values
- Calculate lightness: (max + min) ÷ 2
- Calculate saturation based on lightness
- Calculate hue based on which channel is dominant
For rgb(255, 87, 51):
- Normalized: 1.0, 0.34, 0.2
- Max = 1.0, Min = 0.2
- Lightness = (1.0 + 0.2) ÷ 2 = 0.6 = 60%
- Saturation = 100%
- Hue = 9°
- Result:
hsl(9, 100%, 60%)
Accessibility: Contrast Ratios
Color format choice affects accessibility. WCAG 2.1 requires:
- Normal text: contrast ratio of at least 4.5:1 against the background
- Large text (18pt+ or 14pt+ bold): contrast ratio of at least 3:1
- UI components: contrast ratio of at least 3:1
HSL makes it easy to check and adjust contrast. If your text color doesn’t meet the threshold, simply adjust the lightness value until it does. A common pattern:
/* Ensure accessible text on any background */
.text-on-light {
color: hsl(var(--hue), var(--sat), 15%); /* Dark text */
}
.text-on-dark {
color: hsl(var(--hue), var(--sat), 95%); /* Light text */
}
Quick Contrast Tips
- Pure black (#000000) on pure white (#FFFFFF) = 21:1 (maximum contrast)
- Dark gray (#333333) on white = 12.6:1 (still excellent, softer on the eyes)
- Light gray (#999999) on white = 2.8:1 (fails WCAG for normal text)
- Always test your color combinations — don’t rely on visual judgment alone
Color Picker Tips
- Start with HSL in your design tool — it gives you the most control
- Use a consistent hue — pick 2–3 hues for your entire palette
- Vary saturation and lightness — this creates depth without chaos
- Test in both light and dark mode — colors that work in one may fail in the other
- Use 5% lightness increments — for systematic color scales (50, 55, 60, 65…)
- Avoid pure saturated colors — they’re harsh on screens. Drop saturation to 70–85% for a more refined look
Convert Colors Instantly
Don’t waste time doing hex math by hand. Use our free Color Converter to instantly convert between HEX, RGB, HSL, and other color formats. Just paste any color value and get all equivalent representations at once.
Understanding color formats is a small investment that pays off every time you write CSS. Choose the right format for the job, build systematic palettes, and always keep accessibility in mind.