HSL vs HSV vs HSI: what's the difference and why it matters
color design developer-tools
HSL vs HSV vs HSI: what's the difference and why it matters
If you have used a color picker, you have probably seen HSL (Hue, Saturation, Lightness) and HSV (Hue, Saturation, Value). They look almost identical — same hue wheel, same saturation axis — but they compute the "lightness" axis differently, and that difference affects every color you pick.
This guide explains the math, shows visual examples, and helps you pick the right space for your use case.
Want to convert between HEX, RGB, HSL, and HSV right now? Use the free Color Converter.
The three spaces at a glance
All three spaces share the same hue axis (0-360 degrees around the color wheel). They differ in the second and third axes:
| Space | Full name | Second axis | Third axis |
| HSL | Hue, Saturation, Lightness | Saturation (0-100%) | Lightness (0-100%, 50% = pure color) |
| HSV | Hue, Saturation, Value | Saturation (0-100%) | Value (0-100%, 100% = pure color) |
| HSI | Hue, Saturation, Intensity | Saturation (0-100%) | Intensity (average of R, G, B) |
The key difference:
- In HSL, 100% Lightness is always white, regardless of saturation.
- In HSV, 100% Value is the purest form of the hue, and white only appears when saturation is 0%.
- In HSI, Intensity is the arithmetic mean of R, G, B — used mostly in image processing, not in design tools.
The math (simplified)
Assume R, G, B are normalized to 0-1. Let max = max(R, G, B) and min = min(R, G, B) and delta = max - min.
Hue (same for all three)
If max == min: H = 0 (gray, no hue)
If max == R: H = 60 * ((G - B) / delta mod 6)
If max == G: H = 60 * ((B - R) / delta + 2)
If max == B: H = 60 * ((R - G) / delta + 4)
Hue is 0-360 degrees. 0 = red, 120 = green, 240 = blue.
Saturation
HSL and HSV compute saturation differently:
HSL: S = delta / (1 - |2L - 1|) where L = (max + min) / 2
HSV: S = delta / max (undefined if max == 0)
In HSL, saturation depends on lightness. In HSV, saturation depends only on the max channel.
Lightness / Value / Intensity
HSL Lightness: L = (max + min) / 2
HSV Value: V = max
HSI Intensity: I = (R + G + B) / 3
This is the crux: HSL averages the max and min, HSV takes only the max, HSI averages all three.
Why the difference matters
Pure colors
For a pure saturated color like red rgb(255, 0, 0):
- HSL: H=0, S=100%, L=50%
- HSV: H=0, S=100%, V=100%
- HSI: H=0, S=100%, I=33%
White
For white rgb(255, 255, 255):
- HSL: H=undefined (or 0), S=0%, L=100%
- HSV: H=undefined (or 0), S=0%, V=100%
- HSI: H=undefined, S=0%, I=100%
Half-bright red
For rgb(128, 0, 0) — a dark red:
- HSL: H=0, S=100%, L=25%
- HSV: H=0, S=100%, V=50%
- HSI: H=0, S=100%, I=43%
Visual intuition
- HSL is symmetric: L=0% is always black, L=100% is always white, L=50% is the pure hue. This makes it intuitive for designers — you can reason about "lighter" and "darker" independently of saturation.
- HSV is asymmetric: V=100% is the pure hue, and decreasing V moves toward black. White is not at V=100% unless S=0%. This makes it intuitive for painters — you pick a hue, then decide how "pure" it is (S), then decide how dark it is (V).
- HSI is used in computer vision because Intensity corresponds to the actual perceived brightness average, which is useful for edge detection and segmentation.
When to use which
Use HSL when:
- You are building a color picker for designers. The symmetry (L=50% = pure hue) is intuitive.
- You are generating color schemes (complementary, triadic) — the math is cleaner.
- You are working with CSS, which natively supports
hsl(). - You are adjusting the lightness of a color while keeping the hue and saturation fixed.
color: hsl(210, 80%, 50%); / a medium blue /
color: hsl(210, 80%, 30%); / the same blue, darker /
color: hsl(210, 80%, 70%); / the same blue, lighter /
Use HSV when:
- You are building a color picker that mimics traditional paint mixing (Photoshop's color picker uses HSV).
- You are working with image processing where "value" corresponds to the brightest pixel channel.
- You are generating gradients where you want to fade from a pure hue to black.
Use HSI when:
- You are doing computer vision (OpenCV uses HSI-like spaces for some operations).
- You need intensity to match perceived brightness for segmentation.
- You are implementing algorithms that assume intensity is the channel average.
The CSS angle
CSS supports hsl() and hwb() (HWB = Hue, Whiteness, Blackness) natively. It does not support hsv() directly. If you want HSV-like behavior in CSS, you can use hwb():
/ HWB: hue, then how much white to mix in, then how much black to mix in /
color: hwb(210 0% 0%); / pure blue /
color: hwb(210 30% 0%); / blue with 30% white mixed in /
color: hwb(210 0% 30%); / blue with 30% black mixed in /
HWB is essentially HSV turned inside out — instead of saturation and value, you specify how much white and black to add. It is intuitive and well-supported in modern browsers.
Conversion gotchas
HSL to RGB
function hslToRgb(h, s, l) {
h /= 360; s /= 100; l /= 100;
let r, g, b;
if (s === 0) {
r = g = b = l;
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) 6 t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) (2/3 - t) 6;
return p;
};
const q = l < 0.5 ? l (1 + s) : l + s - l s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [Math.round(r 255), Math.round(g 255), Math.round(b * 255)];
}
HSV to RGB
function hsvToRgb(h, s, v) {
h /= 360; s /= 100; v /= 100;
const i = Math.floor(h * 6);
const f = h * 6 - i;
const p = v * (1 - s);
const q = v (1 - f s);
const t = v (1 - (1 - f) s);
let r, g, b;
switch (i % 6) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
}
return [Math.round(r 255), Math.round(g 255), Math.round(b * 255)];
}
The RuMystic Color Converter implements both of these and handles all the edge cases (grays, pure colors, overflow).
Common mistakes
Mistake 1: Treating HSL Lightness and HSV Value as the same
They are not. hsl(0, 100%, 50%) is pure red. hsv(0, 100%, 50%) is dark red. If you copy a color from an HSV picker into an HSL field, you get a different color.
Mistake 2: Assuming 100% saturation means "most colorful"
In HSL, 100% saturation at L=50% is the pure hue. At L=90%, 100% saturation is a pastel. At L=10%, 100% saturation is a deep shadow. Saturation only means "pure hue" relative to the lightness.
Mistake 3: Using HSL for perceived brightness
HSL Lightness is the average of the max and min RGB channels. It does not match perceived brightness, which is weighted toward green. A pure blue hsl(240, 100%, 50%) looks darker to the human eye than a pure green hsl(120, 100%, 50%), even though they have the same Lightness.
For perceived brightness, use the relative luminance formula:
Y = 0.2126 R + 0.7152 G + 0.0722 B
Or use a perceptual color space like OKLab.
Try it yourself
Open the free RuMystic Color Converter:
- Convert between HEX, RGB, HSL, and HSV.
- See all four representations update live as you adjust any one.
- Copy any format with one click.
- No upload — your color stays in your browser.