StringMash.com

HSL to hex converter

hsl() values to a hex code, with the working.

Conversion
18 characters
Updates as you type
Hex#3366CC
RGBrgb(51, 102, 204)
HSLhsl(220, 60%, 50%)
HSV (HSB)hsv(220, 75%, 80%)
CMYKcmyk(75%, 50%, 0%, 20%)
Nearest CSS nameroyalblue
Contrast with white5.37:1 (AA)
Contrast with black3.91:1 (AA large text only)
The swatch and working are below

Show the steps
Aa blackAa white
  1. Write saturation and lightness as fractions: S = 0.6, L = 0.5. The hue is H = 220°.
  2. Chroma: C = (1 − |2L − 1|) × S = 1 × 0.6 = 0.6.
  3. X = C × (1 − |(H ÷ 60) mod 2 − 1|) = 0.6 × 0.333 = 0.2.
  4. m = L − C ÷ 2 = 0.5 − 0.3 = 0.2.
  5. H ÷ 60 = 3.667, which is from 3 to 4, so red, green and blue start as (0, X, C) = (0, 0.2, 0.6).
  6. Add m to each and multiply by 255: red 51, green 102, blue 204. Rounded, rgb(51, 102, 204).
  7. Write each number from 0 to 255 as two hex digits: divide by 16, and the answer and the remainder are the two digits (10 to 15 are A to F).
  8. Red: 51 ÷ 16 = 3 remainder 3, so 33.
  9. Green: 102 ÷ 16 = 6 remainder 6, so 66.
  10. Blue: 204 ÷ 16 = 12 remainder 12, so CC.
  11. Put them together after a #: #3366CC.
  12. Contrast: 5.37:1 against white and 3.91:1 against black, so white text reads better on it.

Using the converter

Paste an hsl() value from a stylesheet, such as hsl(220, 60%, 50%) or hsl(220 60% 50%). Three bare numbers, hue first, work too. The hex code appears with a swatch.

If the value has an alpha, such as hsl(220 60% 50% / 0.5), the hex code gets a fourth pair for it.

How HSL becomes hex

Write saturation S and lightness L as fractions. Chroma is C = (1 − |2L − 1|) × S. Then X = C × (1 − |(H ÷ 60) mod 2 − 1|) and m = L − C ÷ 2.

The hue's 60° sector decides which channel gets C, which gets X and which gets 0. Add m to each, multiply by 255 and round, then write each number as two hex digits.

The six hue sectors

HueRed, green, blue before adding m
0° to 60°C, X, 0
60° to 120°X, C, 0
120° to 180°0, C, X
180° to 240°0, X, C
240° to 300°X, 0, C
300° to 360°C, 0, X

A worked example

For hsl(220, 60%, 50%), C = (1 − |1 − 1|) × 0.6 = 0.6. H ÷ 60 = 3.667, and 3.667 mod 2 = 1.667, so X = 0.6 × (1 − 0.667) = 0.2. m = 0.5 − 0.3 = 0.2.

220° is in the cyan to blue sector, (0, X, C), which gives (0, 0.2, 0.6) and then (0.2, 0.4, 0.8) after adding m. Times 255 that's 51, 102 and 204, which in hex are 33, 66 and CC. The answer is #3366CC.

A lightness ladder in hex

Keeping hue and saturation and stepping the lightness gives a set of shades, which is how many design systems build a palette.
Lightnesshsl(220, 60%, …)hsl(32, 100%, …)hsl(140, 40%, …)
10%#0A1429#331B00#0F2416
20%#142952#663600#1F472C
30%#1F3D7A#995200#2E6B42
40%#2952A3#CC6D00#3D8F58
50%#3366CC#FF8800#4DB36F
60%#5C85D6#FFA033#70C28B
70%#85A3E0#FFB866#94D1A8
80%#ADC2EB#FFCF99#B8E0C5
90%#D6E0F5#FFE7CC#DBF0E2

HSL compared with HSV

Both models share the same hue. They differ in the other two numbers. In HSL, lightness 50% is the pure colour, 0% is black and 100% is white, so a colour can be lightened or darkened from the middle.

In HSV (also called HSB), the pure colour sits at 100% value and white is 0% saturation at 100% value. hsl(220, 60%, 50%) and hsv(220, 75%, 80%) are the same blue. CSS reads hsl() but not hsv(), and RGB to HSV has the other model.

Questions

Does hsl() to hex lose anything?

Hex has 256 steps per channel, so very close hsl() values can give the same hex code. Going from hex to HSL with whole numbers and back can also move a channel by one step.

Why does lightness 100% always give white?

At 100% lightness, C is 0 and m is 1, so every channel is 255 whatever the hue and saturation.

Sources

Added and reviewed . What's new