HSL to HEX

Convert hue, saturation and lightness values into the hex codes CSS and design tools expect.

Runs on your deviceDesign & ColorWorkingNo account needed

What this tool does

HSL to HEX reads each line of your input as a hue, saturation and lightness triple and writes the sRGB hex code a browser would paint for it. Both spellings are accepted — hsl(217, 91%, 60%) and hsla(160, 84%, 39%, 0.5) — and so is a bare triple such as 217 91 60, because a line carrying three or more loose numbers is read as HSL without needing the function wrapper. Inside the brackets the hue may carry a unit: deg, rad, grad and turn are all converted before the arithmetic, and the CSS keyword none is read as zero. A bare triple has room for neither, so 217deg 91% 60% written without the hsl() around it is refused rather than guessed at.

Four settings shape the code that comes back. Uppercase letters turns #3c83f6 into #3C83F6. The 3-digit form is used only where every pair is a doubled digit, so #ffffff shortens to #fff while #3c83f6 is left at full length. The leading hash can be switched off for fields that want bare digits, and a translucent colour either becomes an 8-digit #RRGGBBAA code or has its alpha channel dropped. Results are drawn as a grid of swatch cards, not as a table: each card paints the colour, then prints the converted code and the line you typed beneath it, and the copy button hands back the hex codes alone, one per line. Two things about that grid are worth knowing — the rgb() equivalent is worked out for every line but is not shown anywhere on the page, and the caption written across the swatch itself is always uppercase and always keeps its hash, whatever the case and hash settings say. Up to 200 colours convert in a run; blank lines and lines beginning with // or a hash and a space are skipped, so a pasted palette can keep its section headings.

Two behaviours are worth knowing before you trust the result. Out-of-range numbers are corrected rather than refused: the hue wraps modulo 360, so 380 is treated as 20, while saturation and lightness are clamped between 0 and 100, which means a mistyped 120% quietly becomes 100% and you get a colour back instead of an error. The same silence swallows a triple that was never HSL in the first place — hand this HSL colour converter the RGB values 255 0 0 and it reads them as hue 255, saturation 0%, lightness 0%, and returns #000000 without a murmur. The second is that hex is the coarser format: HSL is continuous, hex stores eight bits per channel, so hsl(217, 91%, 60%) lands on #3c83f6, whose exact HSL is 217.097, 91.176%, 60%. All of it happens in this browser tab — the list is not uploaded, and once the page has loaded it keeps converting with the network switched off.

There is no service worker behind the page, so it has to be loaded at least once while you are online; after that the arithmetic needs nothing from the network.

How to use it

  1. One colour to a line. hsl() or hsla() notation, or a bare triple like 217 91 60. Percent signs on saturation and lightness are optional, and the deg, rad, grad and turn hue units work inside the brackets only.
  2. Pick the letter case and the length. Uppercase gives #3C83F6 for consistency with an existing sheet. The 3-digit form applies only where the pairs allow it, so most codes stay at six digits.
  3. Say what should happen to translucency. Leave the default to write an 8-digit #RRGGBBAA code, or choose to drop the alpha channel and get the flat six-digit colour underneath it.
  4. Read the swatches, or copy the column. Every line comes back as a card: the colour itself, the converted code below it, and your original input under that. Copy output gives you the hex codes on their own, one per line.

Processing & privacy

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

Common use cases

Committing a generated ramp as tokens

Palettes are often reasoned about in HSL, where lightness is a number you can step evenly, but token files and brand documents expect hex.

Filling a field that accepts hex only

SVG fill attributes, chart libraries, theme settings screens and most colour inputs want six digits and reject hsl() outright.

Converting a whole scale in one pass

A lightness ramp written as a block of hsl() lines goes in as it stands and comes back as a column ready to paste into a stylesheet.

Sanity-checking an HSL value

The card painted for each line shows what the numbers actually produce, which catches a hue typed one digit out before it reaches review.

Questions

Is the palette I paste in sent anywhere?
No. The parsing and the arithmetic run in this browser tab, so the colours stay where you pasted them, and an open page carries on converting with the connection pulled.
Can I convert back and get my original numbers?
At the default settings, usually yes. HEX to HSL rounds to whole numbers unless you tell it otherwise, so hsl(217, 91%, 60%) → #3c83f6 → hsl(217, 91%, 60%) returns what you typed. Raise its decimal places and the loss becomes visible: #3c83f6 is really hsl(217.1, 91.2%, 60%). Either way the pair settles after one lap instead of drifting a little further on each one.
What happens to a hue of 380 or a saturation of 120%?
They are corrected silently. The hue wraps around the circle, so 380 becomes 20, and saturation and lightness are clamped to the 0–100 range. Nothing is rejected, so a typo produces a plausible colour rather than a warning — check the swatch if a value looked unusual.
Why is the alpha in my 8-digit code slightly off?
Hex stores alpha as a single byte. An alpha of 0.5 is written as the pair 80, which is 128 out of 255, or 0.502 when read back. Only 0 and 1 land exactly; every fraction between them is rounded to the nearest of 256 steps.
Will an 8-digit hex code work in my app?
Not everywhere. The output follows CSS Color 4 order, #RRGGBBAA, which current browsers understand. Android colour resources put alpha first, as #AARRGGBB, and plenty of image editors and older tooling reject eight digits altogether — choose to drop the alpha channel when the destination is one of those.
Why did my colour not shorten to three digits?
The short form exists only when both digits of every pair match, because that is the rule CSS expands by. #3c83f6 has no matching pair, so shortening it would change the colour. With alpha included the same rule produces a four-digit code.
Can I paste hex, rgb() or colour names into it as well?
Yes. Any CSS colour value is read, including the colour names, rgb(), hwb(), lab(), lch(), oklab(), oklch() and color(srgb …), so a mixed list converts without sorting first. Everything is treated as sRGB with no profile handling, and a colour outside that gamut has each channel pinned to its nearest legal value rather than being gamut-mapped — oklch(0.9 0.4 140) arrives as a flat #00ff00, with the hue and the lightness moved, not only the intensity.
Careful with bare triples — which model are they read as?
HSL, always. A line of loose numbers is fed to hsl(), so an RGB triple pasted by mistake converts to something unrelated: 255 0 0 becomes #000000, not red. Wrap RGB values in rgb() on the line, or send them to RGB to HEX instead.
What if I have more than 200 lines?
The run stops and reports the number of colour lines it counted rather than truncating the list. Split it into batches; the cap is what stops a mispasted document from freezing the tab.

Related tools