Color Models for Web Development
Same colors, different notations. Pick the right one for the job and your code stays readable.
RGB (Red, Green, Blue)
The foundation of digital color. Every color is a mix of red, green, and blue light.
Syntax
/* Functional notation */
color: rgb(255, 0, 0); /* Red */
color: rgb(0, 255, 0); /* Green */
color: rgb(0, 0, 255); /* Blue */
color: rgb(255, 255, 255); /* White */
color: rgb(0, 0, 0); /* Black */
/* With alpha (transparency) */
color: rgba(255, 0, 0, 0.5); /* 50% transparent red */
color: rgb(255 0 0 / 50%); /* Modern syntax */
How It Works
Each channel ranges from 0 to 255 (8 bits, 256 values per channel).
Red: 0 -------------------- 255
Green: 0 -------------------- 255 16.7 million possible colors
Blue: 0 -------------------- 255
Common RGB Values
| Color | RGB |
|---|---|
| Black | rgb(0, 0, 0) |
| White | rgb(255, 255, 255) |
| Red | rgb(255, 0, 0) |
| Green | rgb(0, 255, 0) |
| Blue | rgb(0, 0, 255) |
| Yellow | rgb(255, 255, 0) |
| Cyan | rgb(0, 255, 255) |
| Magenta | rgb(255, 0, 255) |
| Gray | rgb(128, 128, 128) |
When to Use RGB
- When working with code that outputs RGB
- When you need precise control over individual channels
- For programmatic color manipulation
Drawbacks
RGB is not intuitive. Quick: what color is rgb(147, 112, 219)? Hard to picture. (It is a medium purple.)
HEX (Hexadecimal)
HEX is RGB written in base-16. Same colors, different notation.
Syntax
color: #FF0000; /* Red */
color: #00FF00; /* Green */
color: #0000FF; /* Blue */
color: #FFFFFF; /* White */
color: #000000; /* Black */
/* Shorthand (when each pair is identical) */
color: #F00; /* Same as #FF0000 */
color: #0F0; /* Same as #00FF00 */
color: #FFF; /* Same as #FFFFFF */
/* With alpha (8-digit hex) */
color: #FF000080; /* 50% transparent red */
Reading HEX Values
#FF5733
││││││
││││└┴── Blue: 0x33 = 51
││└┴──── Green: 0x57 = 87
└┴────── Red: 0xFF = 255
Hexadecimal digits: 0 1 2 3 4 5 6 7 8 9 A B C D E F
Quick conversions:
00= 080= 128 (halfway)FF= 255
When to Use HEX
- The default format in design tools and codebases
- Compact
- Easy to copy and paste from design tools
- Good for color constants
Drawbacks
Same problem as RGB. Not intuitive for manipulation. What color is 20% lighter than #3498db? You cannot tell by looking.
HSL (Hue, Saturation, Lightness)
The most intuitive model for designers and developers. It maps directly to how you think about color.
Syntax
color: hsl(0, 100%, 50%); /* Red */
color: hsl(120, 100%, 50%); /* Green */
color: hsl(240, 100%, 50%); /* Blue */
/* With alpha */
color: hsla(0, 100%, 50%, 0.5); /* 50% transparent red */
color: hsl(0 100% 50% / 50%); /* Modern syntax */
The Three Components
Hue (0 to 360): position on the color wheel.
0° / 360° = Red
60° = Yellow
120° = Green
180° = Cyan
240° = Blue
300° = Magenta
Saturation (0% to 100%): intensity of the color.
0% = Gray (no color)
50% = Muted
100% = Vivid, pure color
Lightness (0% to 100%): light to dark.
0% = Black
50% = Pure hue
100% = White
Visual Representation
Saturation ->
100% ┌────────────────────┐
│ Vivid │
│ │
50% │ Muted │ ^
│ │ Lightness
0% │ Gray───────────────│
└────────────────────┘
0% 50% 100%
Creating Color Variations with HSL
This is where HSL pays off:
:root {
/* Base color */
--primary: hsl(220, 90%, 50%);
/* Lighter: bump lightness */
--primary-light: hsl(220, 90%, 70%);
/* Darker: drop lightness */
--primary-dark: hsl(220, 90%, 30%);
/* Muted: drop saturation */
--primary-muted: hsl(220, 40%, 50%);
/* Hover: slightly darker */
--primary-hover: hsl(220, 90%, 45%);
}
When to Use HSL
- Color manipulation: tints, shades, hover states
- Color scales: consistent lightness or saturation steps
- Design systems: predictable relationships between colors
- Dark mode: easy to flip lightness values
- Accessibility: quick contrast adjustments
HSL is Best for CSS Custom Properties
:root {
--hue-primary: 220;
--hue-success: 142;
--hue-warning: 38;
--hue-error: 0;
}
.button-primary {
background: hsl(var(--hue-primary), 90%, 50%);
}
.button-primary:hover {
background: hsl(var(--hue-primary), 90%, 45%);
}
.text-primary-light {
color: hsl(var(--hue-primary), 70%, 70%);
}
HSB/HSV (Hue, Saturation, Brightness/Value)
Used by design tools (Photoshop, Figma) but not directly supported in CSS.
How It Differs from HSL
HSL Lightness: HSB Brightness:
100% = White 100% = Full color
50% = Full color 50% = Darker
0% = Black 0% = Black
In HSB:
- Brightness 100% + Saturation 100% = vivid color
- Brightness 100% + Saturation 0% = white
If your design tool gives you HSB, convert to HSL or RGB before pasting into CSS.
Comparison Table
| Model | Format | Intuitive? | CSS Support | Best For |
|---|---|---|---|---|
| RGB | rgb(255, 128, 0) | No | Yes | Programmatic manipulation |
| HEX | #FF8000 | No | Yes | Constants, copy/paste |
| HSL | hsl(30, 100%, 50%) | Yes | Yes | Design work, variations |
| HSB | hsb(30, 100%, 100%) | Yes | No | Design tools only |
Converting Between Models
In JavaScript
// HEX to RGB
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
// RGB to HSL
function rgbToHsl(r, g, b) {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b), min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
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: h * 360, s: s * 100, l: l * 100 };
}
In Browser DevTools
Most browser DevTools let you click a color value and cycle through formats (Shift+Click on the color swatch in Chrome or Firefox).
Modern CSS: OKLCH and LCH
Newer color spaces that are more perceptually uniform. Equal steps in the values produce equal perceived differences.
/* LCH: Lightness, Chroma, Hue */
color: lch(50% 100 270);
/* OKLCH: improved version */
color: oklch(60% 0.15 250);
Browser support is now wide enough for production work as of 2026. They are better for:
- Perceptually even color scales
- Consistent perceived contrast across hues
- Wider color gamut displays (P3, Rec2020)
HSL still handles most everyday needs. Reach for OKLCH when scales feel uneven across hues.
Practical Recommendations
- Store colors as HEX in design tokens and constants.
- Use HSL in CSS when you need variations.
- Use RGB in JavaScript for color math.
- Compose CSS custom properties from HSL parts for theming.
:root {
/* Define base colors */
--color-primary-h: 220;
--color-primary-s: 90%;
--color-primary-l: 50%;
/* Compose full color */
--color-primary: hsl(
var(--color-primary-h),
var(--color-primary-s),
var(--color-primary-l)
);
/* Easy variations */
--color-primary-light: hsl(
var(--color-primary-h),
var(--color-primary-s),
70%
);
}
Summary
| Model | Remember |
|---|---|
| RGB | 0 to 255 per channel, foundation of digital color |
| HEX | RGB in base-16, most common format in tools |
| HSL | Hue (0 to 360), Saturation (0 to 100%), Lightness (0 to 100%). Use this. |
| HSB | Design tools use it. Convert to HSL for CSS. |
Next: 03-color-wheel.md covers how colors relate on the wheel.