HEX to HSL

Read a hex colour as hue, saturation and lightness — a whole palette at a time.

Runs on your deviceDesign & ColorWorkingNo account needed

What this tool does

HEX to HSL reads each line as a colour and restates it in the HSL colour model: an angle on the colour wheel, a saturation percentage and a lightness percentage. The point of the change is that those three numbers come apart. Lower the lightness and you have a pressed state; drop the saturation and you have a muted variant; hold the hue and the family stays together. A hex code offers no such handle, because every edit is arithmetic on three channels at once.

Three notations are offered: legacy hsl(217, 91%, 60%) with commas, the space-separated modern form hsl(217 91% 60%), and a bare 217, 91%, 60% for dropping into a variable — that last one loses the wrapper but keeps the percent signs. Translucency carries through on its own — an eight-digit code such as #10B98180 comes back as hsla(160, 84%, 39%, 0.502) in legacy notation and uses the slash form in the modern one. There is no switch to force or suppress it, so an opaque colour never prints an alpha and a translucent one always does. Results arrive as a grid of swatch cards, up to 200 colours a run: each card paints the colour, repeats the line you typed and prints the HSL value under it, while Copy output hands back the HSL values alone, one to a line, in the order you pasted them.

The decimal places control matters more than it looks. Zero is the default and the CSS convention, and it is lossy. Rounding the hue to a whole degree and both percentages to whole numbers moves most colours: #3B82F6 becomes hsl(217, 91%, 60%), and converting that back lands on #3c83f6, one step out on two channels. Across a random sample of 300,000 sRGB colours, close to nine in ten failed to return to their original hex at zero decimals, drifting by as much as five per channel; at one decimal place none of that sample drifted at all. Use zero for hand-written CSS, one or two whenever the value has to survive a return trip.

Two limits are worth knowing before you read anything into a number. HSL lightness is not perceived brightness — it is the midpoint between the highest and lowest sRGB channel, which puts pure yellow and pure blue both at 50% even though one is dazzling and the other is dark, so judge legibility with WCAG Contrast Checker rather than by comparing L values. Saturation misbehaves at the extremes for a related reason, being scaled by how far the lightness sits from the middle: a barely tinted near-white like #fffefe reports full saturation. All of it is computed in this browser tab from sRGB numbers, so the list is not sent anywhere and the page still converts with the network off.

How to use it

  1. Paste the palette, one colour to a line. Hex with or without the leading hash, in 3, 4, 6 or 8 digits. Blank lines are skipped, and so are lines beginning with // or a hash and a space, so a palette can keep its section headings.
  2. Pick the output notation. Legacy hsl() with commas for the broadest support, the modern space-separated form for CSS Color 4, or the bare triple when the values are going into code rather than a stylesheet — saturation and lightness keep their percent signs there too.
  3. Decide how precise the triplet should be. Anything from zero to three decimal places, applied to hue, saturation and lightness alike. Alpha ignores the setting: it is rounded to three decimal places and printed without trailing zeros, so 0.502 stays 0.502 while an alpha byte of 33 prints as 0.2.
  4. Check the swatches, then take the HSL list. Each card puts the rendered colour above the line you typed and the value it produced, which makes a mistyped digit obvious before you paste anything. Copy output gives you the HSL values only, nothing else from the card.

Processing & privacy

Runs on your device. Your file is processed directly in this browser.

Common use cases

Building hover and pressed states

Take the brand colour into HSL, move the lightness by eight or ten points, and the variant stays recognisably the same colour instead of drifting.

Rewriting a stylesheet in hsl()

An HSL triplet tells a reader what the colour actually is; a hex code does not. Converting the palette in one pass keeps every value in the file consistent.

Working out why two brand colours clash

Convert both and compare the first number in each triplet: that is the angle between them on the wheel. A few degrees apart usually means somebody mistyped a code rather than chose a second colour.

Feeding a tint and shade generator

Ramp builders and design token scripts want the three components rather than a hex string. The bare values notation strips the hsl() wrapper for you, although a script expecting plain numbers still has to remove the two percent signs.

Questions

Does the palette get sent to a server?
No. Every line is read and converted by JavaScript inside this tab, and no request goes out while it works, so an unreleased brand palette stays on your machine and the page keeps converting once the connection is switched off.
Where are the hue, saturation and lightness columns?
Not drawn on the page. The processor does work each component out separately — and puts them in a five-column table behind the scenes — but the output panel renders the swatch grid instead, so on screen the three numbers only appear inside the composed hsl() string. Read them off that string, or parse it in whatever script consumes the list.
Why does converting back not return my original hex?
Rounding. At the default of zero decimal places #3B82F6 is written as hsl(217, 91%, 60%), and that rounded triplet converts back to #3c83f6. Raise the decimal places to one or two and the round trip holds; the setting exists precisely for that.
Why does grey come out with a hue of 0?
Because it has no hue to report. When red, green and blue are equal there is no angle on the wheel, so the formula falls back to zero and #808080 prints as hsl(0, 0%, 50%). Read that zero as absent rather than as red — black and white do the same thing.
Can I paste something other than hex?
Yes. Colour names, transparent, rgb(), hsl(), hwb(), lab(), lch(), oklab(), oklch() and color(srgb …) are all read, so a mixed list from a stylesheet converts as it stands. Anything outside the sRGB gamut is clamped channel by channel before the HSL numbers are worked out.
Is HSL the same as HSB or HSV?
No, and swapping one for the other produces wrong colours. Value in HSV is the highest channel, which makes pure red 100% value, while lightness in HSL is the midpoint of the highest and lowest, which makes the same red 50% lightness. Only the hue agrees between the two models.
What happens with a long list?
Up to 200 colours convert in one run. Past that the job stops and reports the number of lines it counted rather than truncating silently, so a large palette needs splitting into batches.
Can it go the other way?
Yes. HSL to HEX takes hsl() values back to hex codes, and HEX to RGB covers the third common notation. If the lightness edits are heading towards a full scale, Color Shades builds the tints and shades directly.

Related tools