HSL to RGB Converter

rgb(60, 131, 246)hsl(217, 91%, 60%) · #3C83F6

HSL Channels

°
%
%

Active Hue Sextant

Hue 217° lands in sextant 4 (180–240°) → channels (0, X, C) (cyan → blue)

Try a sample color

Need RGB to HSL instead?

RGB Result

60, 131, 246

rgb(60, 131, 246)

Red

60

Green

131

Blue

246

Hex Equivalent

#3C83F6

Chroma Method Intermediates

Chroma C

0.728

X (middle)

0.279

m (lift)

0.236

Final channels = (sextant value + m) × 255. The lift m is added to all three before scaling.

CSS Code Snippets

color: rgb(60, 131, 246);
background-color: rgb(60, 131, 246);
/* Modern space-separated syntax */
color: rgb(60 131 246);
/* With 50% opacity */
color: rgb(60 131 246 / 50%);

Live Conversion Math for Your Inputs

1. Normalize: S = 0.91, L = 0.60

2.C = (1 − |2L − 1|) × S = 0.7280

3. H′ = 217 / 60 = 3.617 → sextant 4

4.X = C × (1 − |H′ mod 2 − 1|) = 0.2791

5. m = L − C/2 = 0.2360

6.RGB = (channel + m) × 255 → 60, 131, 246

Common HSL to RGB Lookups

ColorHSLRGBPreview
Black0°, 0%, 0%0, 0, 0
White0°, 0%, 100%255, 255, 255
Red0°, 100%, 50%255, 0, 0
Lime120°, 100%, 50%0, 255, 0
Blue240°, 100%, 50%0, 0, 255
Yellow60°, 100%, 50%255, 255, 0
Cyan180°, 100%, 50%0, 255, 255
Magenta300°, 100%, 50%255, 0, 255
CSS Green120°, 100%, 25%0, 128, 0
Amber48°, 89%, 50%241, 196, 14
Slate215°, 16%, 47%101, 117, 139
Violet271°, 81%, 56%146, 52, 234

Click any row to load it into the converter above

How to Use This Tool

  1. 1.Set the Hue slider from 0 to 360 degrees to pick a position on the color wheel — watch the sextant indicator light up
  2. 2.Adjust Saturation (0–100%) for how vivid the color is and Lightness (0–100%) for how light or dark it appears
  3. 3.Read the RGB result in the blue panel, then check the chroma, X, and m intermediates to see exactly how the channels were built
  4. 4.Click any preset or table row to load that color, or hit Copy RGB, Copy hex, or Copy CSS to grab the value for your code

Rate this tool

Six Slices and a Lift: How the Hue Wheel Becomes RGB

An HSL to RGB converter takes a color you can reason about — a hue angle, a saturation percentage, a lightness percentage — and turns it into the three 0–255 integers your screen actually lights up. That last part matters more than it sounds. A monitor has no idea what "217 degrees of hue at 91% saturation" means. It drives red, green, and blue subpixels, full stop. HSL is the language designers and CSS authors think in; RGB is the language hardware renders in. This conversion is the translation layer between the two, and it runs every time a browser paints an hsl() value to the screen.

HSL to RGB conversion diagram showing the hue wheel split into six 60-degree sextants with each labeled by which RGB channels receive full chroma, partial chroma, and zero before a lightness lift produces the final red green blue values

The Direction Browsers Actually Care About

Going from RGB to HSL is something humans do to understand a color. Going from HSL to RGB is something machines do to display one. Every time you write color: hsl(217 91% 60%)in a stylesheet, the browser's style engine converts it to RGB before it ever reaches the compositor — because the frame buffer that holds your page is laid out as red, green, and blue bytes per pixel. There is no "HSL mode" in graphics hardware.

So while the inverse conversion is a convenience, this direction is structural. It's baked into the CSS Color Module specification, which defines hsl() entirely in terms of how it resolves to RGB. If you've ever stored design tokens as HSL channels and needed to feed them to a canvas, a WebGL shader, or an email client that chokes on hsl(), you've needed exactly this conversion. Our RGB to HSL converter handles the analysis direction when you want to read a color instead.

Chroma First, Lift Second

The modern HSL to RGB algorithm doesn't convert lightness directly. It splits the job into two stages: build the colorfulpart first, then lift the whole thing to the right brightness. The colorful part is chroma, and it's where the formula starts.

Chroma measures how far a color is from gray. The formula is C = (1 − |2L − 1|) × S. Notice what that |2L − 1|term does: at L = 0.5 it's zero, so chroma equals saturation outright — colors are most vivid at mid lightness. Push lightness toward 0 (black) or 1 (white) and the term climbs toward 1, crushing chroma to zero. That's the math reason a 95%-lightness color looks nearly white no matter how high you crank saturation: there's barely any chroma left to color it with.

Once you have chroma, you compute two more values. X is the "second" channel — the partial amount that gives the hue its in-between tint, found with X = C × (1 − |(H/60) mod 2 − 1|). And m = L − C/2is the lift: the flat amount added to every channel at the end so the final color hits your requested lightness. Watch these three numbers update live in the converter's indigo panel as you drag the sliders — they're the entire engine.

The Six 60-Degree Slices of the Wheel

Here's the part most explanations gloss over. Hue isn't fed into a single equation — it picks which of six segments of the color wheel you're in, and each segment hard-codes where chroma, X, and zero land among red, green, and blue. Divide the hue by 60 and the integer part is your sextant:

  • 0–60° (red to yellow): channels = (C, X, 0). Red is full, green ramps up, blue is off.
  • 60–120° (yellow to green): (X, C, 0). Green takes over as the full channel.
  • 120–180° (green to cyan): (0, C, X). Red drops out, blue starts climbing.
  • 180–240° (cyan to blue): (0, X, C). Blue becomes the full channel.
  • 240–300° (blue to magenta): (X, 0, C). Red returns as the partial.
  • 300–360° (magenta to red): (C, 0, X). Red is full again, closing the loop.

This is why the hue wheel is circular: sextant six hands off cleanly back to sextant one at 360°, which is the same color as 0°. The converter's sextant indicator highlights which slice your current hue lands in and prints the channel pattern, so you can see, for instance, that a hue of 217° sits in the cyan-to-blue slice where blue gets the full chroma.

Worked Example: hsl(217, 91%, 60%)

Let's convert Tailwind's blue-500, hsl(217, 91%, 60%), by hand and check it against the converter.

  • Normalize: S = 91/100 = 0.91, L = 60/100 = 0.60
  • Chroma: C = (1 − |2(0.60) − 1|) × 0.91 = (1 − 0.20) × 0.91 = 0.80 × 0.91 = 0.728
  • Sextant: H′ = 217 / 60 = 3.617 → sextant 4 (180–240°), pattern (0, X, C)
  • X: H′ mod 2 = 1.617, |1.617 − 1| = 0.617, so X = 0.728 × (1 − 0.617) = 0.728 × 0.383 = 0.279
  • Lift: m = 0.60 − 0.728/2 = 0.60 − 0.364 = 0.236
  • Assemble: (R, G, B) = (0 + m, X + m, C + m) = (0.236, 0.515, 0.964)
  • Scale: ×255 → (60, 131, 246)

Final answer: rgb(60, 131, 246), hex #3C83F6. Drop 217, 91, 60 into the sliders above and the blue panel confirms it. Because this conversion routes through RGB anyway, it's also the first half of any HSL to hex conversion— hex is just RGB written in base 16.

Why Two Tools Disagree by One

Paste the same HSL value into three different converters and you'll occasionally get results that differ by a single unit on one channel. Nobody's wrong — it's rounding order. The conversion produces fractional channel values like 130.7, and turning 130.7 into a byte has three common interpretations: Math.round gives 131, Math.floorgives 130, and rounding the normalized 0–1 value before the ×255 multiply can give yet another answer.

Take hsl(48, 89%, 50%). Round-after-scaling yields rgb(242, 196, 13); some libraries that truncate yield rgb(241, 196, 12). The two ambers are one 8-bit step apart — a brightness difference of roughly 0.4%, completely invisible to the eye. It only bites you in two situations: automated visual-regression tests that compare pixels byte-for-byte, and color-keying where an exact value triggers transparency. If either applies, lock down the rounding mode and don't mix conversion sources.

The Lime-vs-Green Trap

A surprising number of developers assume hsl(120, 100%, 50%) is the CSS color green. It isn't. That HSL value converts to rgb(0, 255, 0) — the blinding pure green that CSS actually names lime. The keyword green is the much darker rgb(0, 128, 0), which is hsl(120, 100%, 25%): same hue, same saturation, but half the lightness.

The trap exists because the X11 color names that CSS inherited were defined before anyone thought in HSL, and green got a mid-tone value while limegrabbed the maximum. So when you're translating a design that calls for "green at full saturation," check the lightness: 50% gives you eye-searing lime, and you almost always want something in the 25–40% range for a green that reads as green. Try both in the converter and the preview banner makes the difference obvious.

A 12-Line Reference Function

The full HSL to RGB conversion fits in a dozen lines of dependency-free JavaScript — the same routine powering the tool above:

function hslToRgb(h, s, l) {
  s /= 100; l /= 100;
  const c = (1 - Math.abs(2 * l - 1)) * s;
  const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
  const m = l - c / 2;
  let [r, g, b] = [0, 0, 0];
  if (h < 60)       [r, g, b] = [c, x, 0];
  else if (h < 120) [r, g, b] = [x, c, 0];
  else if (h < 180) [r, g, b] = [0, c, x];
  else if (h < 240) [r, g, b] = [0, x, c];
  else if (h < 300) [r, g, b] = [x, 0, c];
  else              [r, g, b] = [c, 0, x];
  return [Math.round((r + m) * 255),
          Math.round((g + m) * 255),
          Math.round((b + m) * 255)];
}

Two details keep this correct. The if ladder uses strict less-than against the 60° boundaries so a hue of exactly 120 lands in the green-to-cyan slice, not the previous one. And the (r + m) addition happens before the ×255 scale, never after — flip that order and the lift gets applied in the wrong units, pushing every light color toward white. Once those two are right, the function round-trips cleanly against the converter for every input you can throw at it. When you need to go the other way, our hex to RGB converter handles the base-16 parsing side.

Marko Sinko
Marko SinkoTechnical Tools Editor

Croatian developer with a Computer Science degree from University of Zagreb and expertise in advanced algorithms. Marko builds and verifies the technical tools, number system converters, and scientific calculators across UnitCalcTools, ensuring mathematical precision and developer-friendly interfaces.

Last updated: June 22, 2026LinkedIn

Frequently Asked Questions

hsl(217, 91%, 60%) converts to rgb(60, 131, 246) — Tailwind's blue-500. The chroma comes out to 0.728, the lightness lift m is 0.236, and because the hue 217 falls in the fourth sextant (180–240), blue takes the full chroma while red takes the smallest share. Multiply each normalized channel by 255 and round to land on 60, 131, and 246.
At lightness 50% and saturation 100%, chroma C equals 1.0 — the maximum possible. A hue of 0 sits at the very start of the first sextant, so red gets the full chroma (1.0), green gets X which is 0, and blue is 0. The lift m is 0 because L − C/2 = 0.5 − 0.5 = 0. That produces normalized (1, 0, 0), or rgb(255, 0, 0) after scaling.
Yes. In CSS the hue is a plain number or angle (217 or 217deg), but saturation and lightness are always percentages and the % sign is required — hsl(217, 91%, 60%) is valid, hsl(217, 91, 60) is not and the browser ignores it. Inside conversion math you strip the % and divide by 100, so 91% becomes 0.91 before it enters the chroma formula.
Because HSL has more addressable slots than 8-bit RGB. Integer HSL spans 360 × 101 × 101 = about 3.67 million combinations, but each rounds to one of only 16.7 million RGB colors through a non-uniform mapping, so neighbors collapse together. For example, hsl(210, 60%, 50%) and hsl(211, 60%, 50%) both round to rgb(51, 128, 204). The one-degree hue difference is smaller than a single step on the 0–255 scale.
The m value (m = L − C/2) is the lightness lift added equally to all three channels at the end. Chroma alone only describes the colorful part of the result; m raises the whole color toward white or settles it toward black so the final lightness matches your input. For hsl(120, 100%, 25%) — a dark green — m is 0, but for hsl(120, 100%, 75%) — a pale green — m is 0.5, lifting every channel by about 127 before rounding.
Compute chroma C = (1 − |2L − 1|) × S, find the sextant by dividing hue by 60, derive the middle value X = C × (1 − |(H/60) mod 2 − 1|), assign C, X, and 0 to red, green, and blue based on the sextant, then add m = L − C/2 to each and multiply by 255. The whole routine is about 12 lines with no dependencies — the live converter on this page runs exactly this algorithm.
Yes. hsl(120, 100%, 50%) converts to rgb(0, 255, 0), which is the hex #00FF00 — identical to the CSS named color 'lime', not 'green'. The keyword 'green' is actually the darker rgb(0, 128, 0), equal to hsl(120, 100%, 25%). This catches people out: pure 50%-lightness primaries map to the bright web colors, while the classic 'green' keyword sits at half that lightness.
Off-by-one differences come from rounding order. Some libraries round each channel with Math.round after scaling, others truncate with Math.floor, and a few round the normalized value before multiplying by 255. For hsl(48, 89%, 50%) one approach gives rgb(242, 196, 13) and another rgb(241, 196, 12). Both are within a single 8-bit step and visually identical, but if you need byte-exact output, match the rounding mode of the system you're comparing against.

Related Tools