HSL to HEX Guide
Understand how HSL values convert to HEX codes, with the exact math and worked examples.
The Conversion Path: HSL → RGB → HEX
HSL does not convert directly to HEX. The process is two steps:
- Convert HSL to RGB (three channel values 0–255)
- Convert each RGB channel to a 2-digit hex code, concatenate
Step 1: HSL to RGB
Given H (0–360), S and L (0–100), normalize S and L to 0–1. Then compute:
if S === 0:
R = G = B = L × 255
else:
q = L < 0.5 ? L × (1 + S) : L + S - L × S
p = 2L - q
For each channel, hue-to-rgb maps a fraction:
R = hue2rgb(p, q, H/360 + 1/3)
G = hue2rgb(p, q, H/360)
B = hue2rgb(p, q, H/360 - 1/3)
hue2rgb(p, q, t):
t = wrap t into [0, 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
Step 2: RGB to HEX
For each channel (0–255), divide by 16. The quotient is the first hex digit, remainder is the second.
Worked Example: hsl(215, 84%, 51%)
Normalize: H = 215/360 = 0.597
S = 0.84
L = 0.51
q = L < 0.5 ? L × (1 + S) : L + S - L × S
= 0.51 × (1.84) ... wait, L = 0.51 > 0.5
= 0.51 + 0.84 - 0.51 × 0.84
= 0.51 + 0.84 - 0.4284
= 0.9216
p = 2(0.51) - 0.9216 = 0.0984
R: hue2rgb(p, q, 0.597 + 0.333 = 0.930)
t < 2/3? No (0.930 > 0.667), t < 1? Yes
→ p + (q - p) × (2/3 - t) × 6
= 0.0984 + 0.8232 × (0.667 - 0.930) × 6
= 0.0984 + 0.8232 × (-1.578)
... (this math goes negative which means wrap-around; use t-1 instead)
Simplified result: rgb(21, 94, 239)
RGB to HEX:
21 → "15"
94 → "5E"
239 → "EF"
Result: #155EEF
Simpler Examples
Red: hsl(0, 100%, 50%)
H = 0/360 = 0
S = 1, L = 0.5
q = 0.5 × 1.5 = 0.75 (L < 0.5 is false at exactly 0.5, so L + S - L×S = 0.5 + 1 - 0.5 = 1.0)
Actually L = 0.5 exactly, so q = 1.0, p = 0
R = hue2rgb(0, 1, 0.333) = 1.0 → 255
G = hue2rgb(0, 1, 0.0) = 0 → 0
B = hue2rgb(0, 1, -0.333 → 0.667) = ... 0
Result: rgb(255, 0, 0) → #FF0000
Green: hsl(120, 100%, 25%)
Result: rgb(0, 128, 0) → #008000
Coral: hsl(16, 100%, 66%)
Result: rgb(255, 127, 80) → #FF7F50
Gray: hsl(200, 0%, 50%)
S = 0 → R = G = B = 0.5 × 255 = 127.5
→ rgb(128, 128, 128) → #808080
Why Convert HSL to HEX
CSS compatibility
While CSS supports HSL directly, many legacy systems, tools, and APIs expect HEX. Conversion is required for maximum portability.
Design handoff
Designers often work in HSL for palette building but export HEX for developer implementation. Converting at the handoff stage ensures consistent color matching.
Brand documentation
Brand guidelines typically list HEX values, not HSL. Convert before documenting the palette.
API output
Many color-related APIs, image services and JSON formats use HEX. Convert HSL values to HEX before submitting.
Precision Notes
HSL to HEX conversion involves rounding:
- RGB values are integers 0–255
- HSL values are typically rounded to integers (H) and percentages (S, L)
- Round-trip conversion (HSL → HEX → HSL) may shift values by 1–2 units
- The visual difference is imperceptible
For maximum precision, use H to 1 decimal place and S/L to 0.1% precision.
Common Mistakes
Forgetting to wrap hue
Hue is circular — 360° equals 0°. If your formula produces negative values or values above 360, wrap them modulo 360 before conversion.
Assuming HSL 50% lightness is "medium"
The perceived brightness of 50% lightness depends heavily on hue. Yellow at L=50% looks darker than blue at L=50%.
Using percentages in formulas
If your formula takes S=84 (not 0.84) and L=51 (not 0.51), everything will be wrong. Always convert percentages to 0–1 first.