Convert HEX to HSL

Convert HEX color codes to HSL values for CSS. Get hsl() output from any #rrggbb code to build color scales, adjust lightness, or work with CSS color functions.

ZERO UPLOAD · ALL LOCAL
  1. Drag the crosshair on the gradient canvas to pick a color, or type directly into any format field to convert it instantly.
  2. Use the hue slider to change the color family and the opacity slider (or Opacity % field) to adjust transparency.
  3. The CSS Named field shows the closest CSS color name to your pick. The small swatch beside it shows what that named color actually looks like.
  4. The Contrast Check section shows the WCAG AA / AAA rating for black text and white text on your color.
  5. Click Copy next to any field to copy that format value to your clipboard.

Worked examples for this use case

Brand color → HSL for lightness scale

Before
#c8ff00
After
hsl(74, 100%, 50%)

Adjust the third value (50%) up or down to create lighter or darker variants.

Primary button color → accessible hover state

Before
#3b82f6
After
hsl(217, 91%, 60%)

For a darker hover, change 60% to 50%: hsl(217, 91%, 50%).

Hue
Opacity
Invalid format

Contrast Check

Text
Black on color
Text
White on color

HEX to HSL Color Converter

HSL (Hue, Saturation, Lightness) makes it easy to build color scales and adjust tones without losing the hue. When you have a brand HEX color and need a 10-step lightness scale for a UI, converting to HSL first gives you a predictable starting point.

How the conversion works

Converting HEX to HSL routes through an intermediate RGB step. Each HEX pair decodes to a 0–255 integer, then each channel normalizes to 0–1. From those three normalized values, the algorithm finds the maximum and minimum channel to determine lightness (their average), saturation (their spread divided by the complement of the lightness extremes), and hue (the position of the maximum channel on the 0–360 degree color wheel).1 Consequently, two colors with the same hue and saturation but different lightness share the same hue angle after conversion.

Why the conversion routes through RGB

HSL describes color in terms of perceptual qualities, not channel intensities. To derive hue, saturation, and lightness from three hex-encoded channels, the algorithm first converts to RGB because the relationship between channel values and the resulting hue angle is unambiguous in RGB space. Skipping the intermediate step would require a direct hex-to-HSL formula that is harder to verify and more prone to off-by-one errors in the hue calculation.

The intermediate RGB step also keeps the conversion deterministic across languages and libraries. Because the RGB-to-HSL math is identical everywhere, a value computed in JavaScript matches one computed in Python or a design tool, so the same HEX always yields the same hue, saturation, and lightness regardless of where the conversion runs. That cross-platform stability is why most color libraries route through RGB rather than inventing a bespoke HEX-to-HSL shortcut.

How the hue angle is calculated

The hue depends on which channel is the maximum and which is the minimum. If red is the maximum and blue is the minimum, the hue falls in the yellow-to-red range and is computed as (g - b) / (max - min), scaled to degrees. When green is the maximum, a different formula applies, and when blue is the maximum, yet another. The resulting angle wraps at 360 degrees, so a hue of 0 and a hue of 360 both represent pure red.

Where this comes up

HSL is the format of choice for design token color scales. Starting from a brand HEX, converting to HSL gives a stable hue angle that stays fixed while lightness steps from 5% to 95% generate a full shade ramp. Building on this, CSS custom properties that define palette coordinates for hue and saturation let components construct hsl() values dynamically by referencing those property tokens. Yet any tool that only accepts HEX, including legacy build scripts and certain SVG renderers, requires converting the result back at the end.

Shade ramps for component states

A single brand color needs at least four visual variants for a complete component library: default, hover, active, and disabled. By holding the hue and saturation constant and stepping lightness down for hover and active, then desaturating slightly for disabled, you derive all four states from one HEX input without introducing hue drift. This approach keeps your component palette visually coherent across every button, link, and form field in the project.

When HEX input is the only option

Designers often deliver brand guidelines as HEX values because they are the most compact and universally supported format. If your CSS pipeline is built around HSL coordinates for dynamic theming, you need to convert those HEX brand values to HSL once during token generation and store the resulting hue, saturation, and lightness as your canonical design tokens. This one-time conversion step pays off every time a brand color changes, because you update a single HSL value and every component that references the custom properties updates automatically.

Edge cases and rounding

Achromatic colors, including pure greys, white, and black, have saturation zero and a mathematically undefined hue; most implementations output 0° by convention.1 Rounding floating-point intermediates introduces tiny errors in the hue angle, so a round-trip of HEX to HSL to HEX may differ by 1 in the last RGB channel digit. Furthermore, hsl() in CSS requires percentage suffixes on saturation and lightness, and omitting them produces invalid syntax in CSS 2.1 parsers, though CSS Color Level 4 allows space-separated unitless values in some contexts.2

Why achromatic hues are always zero

When all three RGB channels are equal, the color sits on the grey axis and has no saturation. The hue formula divides by (max - min), which becomes zero for greys, so the result is undefined. Every implementation picks 0° as the convention, which means the hue value for grey is arbitrary and should not be used as a meaningful identifier in your code.

Round-trip precision and when it matters

A round-trip through HSL introduces a small error because the HSL representation has finite precision (whole degrees for hue, whole percentages for saturation and lightness). For most UI work, a difference of 1 in one RGB channel is imperceptible. However, if you are generating a color palette programmatically and need every shade to match a reference exactly, store the original HEX value as the source of truth and derive HSL only for display or manipulation purposes.

Building accessible shade ramps with HSL lightness steps

HSL's lightness channel is the most reliable way to generate accessible shade ramps from a single brand color, and you can build a shade ramp from one HEX color by stepping lightness in the converter. Convert your brand HEX to HSL, then hold the hue and saturation constant while stepping lightness from 95% (near-white) down to 15% (near-black). Each step produces a shade that is perceptually related to the base color, which is essential for creating hover states, disabled states, and text-on-background combinations that meet WCAG contrast requirements.

The key insight is that equal lightness steps in HSL do not produce equal perceived brightness differences across all hues. Yellows at 60% lightness look brighter than blues at 60% lightness.3 For truly perceptually uniform ramps, convert to OKLCH and step the L channel instead. But for quick shade generation where exact perceptual uniformity is not critical, HSL lightness steps are good enough and supported in every browser without polyfills. Building on this, generate your ramp in HSL, then convert each step to HEX for use in your CSS custom properties.

CSS custom properties and dynamic HSL theming

HSL is the natural format for CSS custom property theming because you can decompose a color into its three channels and recompose them dynamically. Define custom properties for hue, saturation, and lightness in your :root, then reference those tokens inside hsl() throughout your stylesheet. To create a dark theme, override only the lightness custom property and every color that references those tokens updates automatically.

This pattern works best when you convert your brand HEX to HSL first and use the HSL coordinates as the canonical token values. Converting #3b82f6 to hsl(217, 91%, 60%) gives you the three channel values to store as separate custom properties. Building on this, CSS Color Level 4 allows space-separated hsl() syntax without commas: hsl(217 91% 60%).2 This is the recommended modern syntax because it works with the slash-separated alpha form: hsl(217 91% 60% / 0.5). The comma syntax is legacy and does not support alpha in a single function call.

HSL versus HSB: why CSS uses HSL and Photoshop uses HSB

CSS uses HSL (Hue, Saturation, Lightness) while Photoshop and most native OS color pickers use HSB (Hue, Saturation, Brightness, also called HSV). The two models share the same hue angle but define saturation and the third channel differently. In HSL, lightness 100% is always white regardless of saturation. In HSB, value 100% at saturation 0% is white, but value 100% at saturation 100% is the most vivid version of the hue.

This difference means you cannot directly copy HSB values from Photoshop into CSS hsl() and expect the same color. You must convert through an intermediate space (RGB or HEX) to get the correct HSL coordinates. Building on this, when a designer gives you HSB values from Photoshop, ask them to provide the HEX or RGB equivalent instead, or convert the HSB to RGB first and then to HSL. The converter on this tool accepts HEX, RGB, and HSL inputs directly, so you can paste any of these formats and get the HSL output without manual conversion.

When to use this

Use this when building a design token color scale, creating hover and active state variants from a base color, or using CSS hsl() for dynamic theme generation.

Examples

Brand color → HSL for lightness scale

Before
#c8ff00
After
hsl(74, 100%, 50%)

Adjust the third value (50%) up or down to create lighter or darker variants.

Primary button color → accessible hover state

Before
#3b82f6
After
hsl(217, 91%, 60%)

For a darker hover, change 60% to 50%: hsl(217, 91%, 50%).

Sources
  1. 1.

    "HSL and HSV," Wikipedia, en.wikipedia.org, accessed June 2026. https://en.wikipedia.org/wiki/HSL_and_HSV

  2. 2.

    "hsl() CSS function," MDN Web Docs, developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/color_value/hsl

  3. 3.

    ColorUI Team, "OKLCH vs HSL: Why Modern Design Systems Pick OKLCH," colorui.io, May 2026. https://colorui.io/blog/oklch-vs-hsl-design-systems

FAQ