CSS hsl() Function
The CSS hsl() function defines colors using hue, saturation, and lightness, with an optional alpha value for transparency.
HSL provides an intuitive way to adjust colors by changing their position on the color wheel, their saturation, or their lightness. The function produces colors in the sRGB color space and can be used anywhere a CSS <color> value is accepted.
Syntax
hsl(hue saturation lightness)
hsl(hue saturation lightness / alpha)
hsl(from color hue saturation lightness)
hsl(from color hue saturation lightness / alpha)
The modern syntax separates color components with spaces and uses a slash before the optional alpha value.
For example:
.box {
background-color: hsl(210 100% 50%);
}
This creates a fully saturated blue with a hue of 210 degrees and a lightness of 50%.
Additional examples:
color: hsl(0 100% 50%);
color: hsl(120 100% 50%);
color: hsl(240 100% 50%);
color: hsl(210 80% 40% / 50%);
color: hsl(210deg 80% 40%);
color: hsl(210, 80%, 40%);
The final example uses the older comma-separated syntax, which remains valid for compatibility.
The function returns a CSS <color> value.
Parameters
The hsl() function uses three color components and an optional alpha component.
| Parameter | Description | Required |
|---|---|---|
hue |
Defines the position on the color wheel using a number or angle. | Yes |
saturation |
Controls color intensity, from gray to fully saturated. | Yes |
lightness |
Controls the amount of lightness, from black to white. | Yes |
alpha |
Controls opacity using a number or percentage. | No |
For example:
hsl(210 80% 45% / 0.75)
This defines a blue color with 80% saturation, 45% lightness, and 75% opacity.
In modern syntax, saturation and lightness can also use numbers, where 100 corresponds to 100%. Percentages remain the most familiar way to express these components.
The modern syntax also supports none for missing components.
How It Works
The hsl() function describes a color using three related components.
- Hue selects the basic color around a circular color wheel.
- Saturation determines how colorful or gray the result appears.
- Lightness determines how dark or light the result appears.
- The optional alpha value determines transparency.
For example:
hsl(210 100% 50%)
The hue selects blue, saturation keeps it fully colorful, and lightness places it halfway between black and white in the HSL model.
Changing only one component produces a related color:
hsl(210 100% 50%)
hsl(210 50% 50%)
hsl(210 100% 75%)
The first is a saturated blue, the second is less saturated, and the third is lighter.
HSL values are converted to sRGB colors for rendering.
Hue
Hue represents the position around a color wheel, measured in degrees.
Common hue values include:
| Hue | Color | Example |
|---|---|---|
| 0° | Red | hsl(0 100% 50%) |
| 60° | Yellow | hsl(60 100% 50%) |
| 120° | Green | hsl(120 100% 50%) |
| 180° | Cyan | hsl(180 100% 50%) |
| 240° | Blue | hsl(240 100% 50%) |
| 300° | Magenta | hsl(300 100% 50%) |
| 360° | Red | hsl(360 100% 50%) |
Hue values wrap around the color wheel. For example, 0 degrees and 360 degrees represent the same hue.
Angles can use deg, rad, grad, or turn units.
hsl(180deg 100% 50%)
hsl(0.5turn 100% 50%)
Both expressions produce cyan.
Complementary hues are 180 degrees apart on the HSL color wheel.
Saturation
Saturation controls the intensity of a color.
A saturation of 100% produces a fully saturated color, while 0% produces a shade of gray.
For example:
hsl(210 100% 50%)
hsl(210 75% 50%)
hsl(210 50% 50%)
hsl(210 25% 50%)
hsl(210 0% 50%)
All five colors use the same hue and lightness, but their saturation decreases.
At 0% saturation, the hue no longer affects the visible color.
For example:
hsl(0 0% 50%)
hsl(120 0% 50%)
hsl(240 0% 50%)
All three produce the same medium gray.
Saturation is useful for creating muted colors, neutral variations, and related color palettes.
Lightness
Lightness controls how light or dark a color appears in the HSL model.
| Lightness | Effect |
|---|---|
0% |
Black, regardless of hue or saturation. |
25% |
A darker version of the selected hue. |
50% |
The midpoint of HSL lightness. |
75% |
A lighter version of the selected hue. |
100% |
White, regardless of hue or saturation. |
For example:
hsl(210 100% 20%)
hsl(210 100% 40%)
hsl(210 100% 60%)
hsl(210 100% 80%)
Each color uses the same hue and saturation but a different lightness.
HSL lightness is not the same as perceived brightness. Different hues with the same lightness percentage can appear noticeably different in brightness.
For accessibility, evaluate the actual contrast ratio rather than relying on HSL lightness alone.
Alpha and Transparency
The optional alpha component controls a color's opacity.
Modern syntax uses a slash before the alpha value.
For example:
background-color: hsl(210 100% 50% / 50%);
This creates a blue color with 50% opacity.
Alpha can be expressed as a number or percentage:
hsl(210 100% 50% / 1)
hsl(210 100% 50% / 0.75)
hsl(210 100% 50% / 0.5)
hsl(210 100% 50% / 0)
hsl(210 100% 50% / 50%)
An alpha value of 1 or 100% is fully opaque. An alpha value of 0 is fully transparent.
The older hsla() function is an alias for hsl().
hsla(210, 100%, 50%, 0.5)
hsl(210 100% 50% / 0.5)
Both expressions represent the same color and opacity.
Alpha changes transparency, not the underlying hue, saturation, or lightness values.
Modern and Legacy Syntax
CSS supports both modern space-separated syntax and legacy comma-separated syntax.
| Feature | Modern Syntax | Legacy Syntax |
|---|---|---|
| Separators | Spaces | Commas |
| Alpha separator | Slash | Comma |
| Transparency | hsl(210 80% 50% / 0.5) |
hsla(210, 80%, 50%, 0.5) |
| Missing components | Supports none. |
Does not support none. |
| Relative colors | Supports from. |
Not supported. |
For example, these are equivalent:
hsl(210 80% 50%)
hsl(210, 80%, 50%)
Do not mix modern and legacy separators.
The following is invalid:
hsl(210, 80% 50%)
Modern syntax is recommended for new CSS because it supports newer color features.
Relative HSL Colors
Relative color syntax allows a new HSL color to be created from an existing color.
The syntax begins with the from keyword:
hsl(from origin-color hue saturation lightness)
hsl(from origin-color hue saturation lightness / alpha)
For example:
.button {
--base-color: hsl(210 80% 45%);
background-color: hsl(from var(--base-color) h s calc(l + 15));
}
The browser extracts the original hue, saturation, and lightness values, then increases the lightness component by 15 percentage points.
Relative HSL syntax provides the following channel keywords:
| Channel | Description |
|---|---|
h |
Original hue, represented as a number in degrees. |
s |
Original saturation, represented as a number from 0 to 100. |
l |
Original lightness, represented as a number from 0 to 100. |
alpha |
Original alpha, represented as a number from 0 to 1. |
For example:
hsl(from red h s l)
hsl(from red h s calc(l + 20))
hsl(from red calc(h + 180) s l)
hsl(from red h s l / 0.5)
The first preserves the original HSL components. The second increases lightness, the third rotates hue by 180 degrees, and the fourth changes opacity.
Relative color syntax is newer than traditional HSL syntax, so check browser support when targeting older browsers.
Missing Color Components
Modern HSL syntax supports the none keyword to represent a missing color component.
For example:
hsl(none 0% 50%)
hsl(210 none 50%)
hsl(210 80% none)
When a missing component is used to render a color directly, it behaves like zero for that component.
For example:
hsl(none 0% 50%)
This renders as a medium gray.
Missing components can also influence color interpolation by allowing a corresponding component to be taken from another color.
The none keyword is not supported in legacy comma-separated HSL syntax.
For ordinary color definitions, explicit values are generally easier for beginners to understand.
Using Custom Properties
CSS custom properties can store HSL colors or individual color components.
For example:
:root {
--primary-color: hsl(210 80% 45%);
}
.button {
background-color: var(--primary-color);
}
This makes the color reusable throughout a stylesheet.
Individual components can also be stored:
:root {
--hue: 210;
--saturation: 80%;
--lightness: 45%;
}
.button {
background-color: hsl(var(--hue) var(--saturation) var(--lightness));
}
Changing one custom property updates every color that uses it.
For example:
.button:hover {
background-color: hsl(var(--hue) var(--saturation) 35%);
}
This creates a darker version of the same hue and saturation.
Example
This example demonstrates six hues around the HSL color wheel.
HTML:
<div class="hsl-demo">
<div class="hsl-demo-item"><div class="hsl-demo-color hsl-red"></div><span>0° Red</span></div>
<div class="hsl-demo-item"><div class="hsl-demo-color hsl-yellow"></div><span>60° Yellow</span></div>
<div class="hsl-demo-item"><div class="hsl-demo-color hsl-green"></div><span>120° Green</span></div>
<div class="hsl-demo-item"><div class="hsl-demo-color hsl-cyan"></div><span>180° Cyan</span></div>
<div class="hsl-demo-item"><div class="hsl-demo-color hsl-blue"></div><span>240° Blue</span></div>
<div class="hsl-demo-item"><div class="hsl-demo-color hsl-magenta"></div><span>300° Magenta</span></div>
</div>
CSS:
.hsl-demo {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
max-width: 420px;
margin: 0 auto;
}
.hsl-demo-item {
text-align: center;
font-size: 13px;
}
.hsl-demo-color {
height: 65px;
margin-bottom: 6px;
border-radius: 4px;
}
.hsl-red { background-color: hsl(0 100% 50%); }
.hsl-yellow { background-color: hsl(60 100% 50%); }
.hsl-green { background-color: hsl(120 100% 50%); }
.hsl-cyan { background-color: hsl(180 100% 50%); }
.hsl-blue { background-color: hsl(240 100% 50%); }
.hsl-magenta { background-color: hsl(300 100% 50%); }
Each swatch uses 100% saturation and 50% lightness. Only the hue changes.
The colors progress around the HSL color wheel in 60-degree increments.
Saturation Example
This example demonstrates how changing saturation affects the same hue.
HTML:
<div class="hsl-saturation-demo">
<div class="hsl-saturation-item hsl-sat-100">100%</div>
<div class="hsl-saturation-item hsl-sat-75">75%</div>
<div class="hsl-saturation-item hsl-sat-50">50%</div>
<div class="hsl-saturation-item hsl-sat-25">25%</div>
<div class="hsl-saturation-item hsl-sat-0">0%</div>
</div>
CSS:
.hsl-saturation-demo {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px;
}
.hsl-saturation-item {
display: grid;
place-items: center;
width: 65px;
height: 65px;
color: #fff;
font-size: 13px;
}
.hsl-sat-100 { background-color: hsl(210 100% 40%); }
.hsl-sat-75 { background-color: hsl(210 75% 40%); }
.hsl-sat-50 { background-color: hsl(210 50% 40%); }
.hsl-sat-25 { background-color: hsl(210 25% 40%); }
.hsl-sat-0 { background-color: hsl(210 0% 40%); }
All five swatches use a hue of 210 degrees and 40% lightness.
As saturation decreases, the blue becomes less colorful until it reaches gray at 0%.
Lightness Example
This example demonstrates how lightness changes the appearance of a color.
HTML:
<div class="hsl-lightness-demo">
<div class="hsl-lightness-item hsl-light-20">20%</div>
<div class="hsl-lightness-item hsl-light-35">35%</div>
<div class="hsl-lightness-item hsl-light-50">50%</div>
<div class="hsl-lightness-item hsl-light-65">65%</div>
<div class="hsl-lightness-item hsl-light-80">80%</div>
</div>
CSS:
.hsl-lightness-demo {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px;
}
.hsl-lightness-item {
display: grid;
place-items: center;
width: 65px;
height: 65px;
color: #fff;
font-size: 13px;
}
.hsl-light-20 { background-color: hsl(210 80% 20%); }
.hsl-light-35 { background-color: hsl(210 80% 35%); }
.hsl-light-50 { background-color: hsl(210 80% 50%); }
.hsl-light-65 { background-color: hsl(210 80% 65%); color: #111; }
.hsl-light-80 { background-color: hsl(210 80% 80%); color: #111; }
All five swatches use a hue of 210 degrees and 80% saturation.
Increasing lightness produces progressively lighter shades. The text changes to dark on the lighter swatches for readability.
hsl() vs. rgb()
The hsl() and rgb() functions both define colors in the sRGB color space, but they describe colors differently.
| Feature | hsl() | rgb() |
|---|---|---|
| Components | Hue, saturation, and lightness. | Red, green, and blue. |
| Color adjustment | Convenient for changing hue, saturation, or lightness. | Convenient for adjusting individual RGB channels. |
| Transparency | Supports an optional alpha value. | Supports an optional alpha value. |
| Color space | sRGB | sRGB |
| Example | hsl(0 100% 50%) |
rgb(255 0 0) |
For example, these represent the same red color:
color: hsl(0 100% 50%);
color: rgb(255 0 0);
color: #ff0000;
Use hsl() when working with related hues and color variations. Use rgb() when specific red, green, and blue channel values are needed.
Neither format automatically guarantees accessible contrast.
Common Uses
The hsl() function is useful for defining and adjusting colors in CSS.
| Use | Description |
|---|---|
| Color palettes | Create related colors by adjusting hue, saturation, or lightness. |
| Buttons | Define normal, hover, and active colors. |
| Backgrounds | Create solid colors and gradient color stops. |
| Typography | Define text colors using HSL values. |
| Transparency | Create partially transparent colors using alpha. |
| Theming | Combine HSL with custom properties to manage site colors. |
| Relative colors | Generate variations from an existing color. |
For example:
.button {
background-color: hsl(210 80% 45%);
color: #fff;
}
.button:hover {
background-color: hsl(210 80% 35%);
}
The hover state uses the same hue and saturation with lower lightness.
Limitations
The hsl() function has several important rules and limitations.
- Hue, saturation, and lightness are required components, although modern syntax permits
nonein place of a component. - Modern syntax uses spaces between components and a slash before alpha.
- Legacy syntax uses commas and requires percentage units for saturation and lightness.
- Modern and legacy separators cannot be mixed.
- Hue values wrap around the color wheel.
- At zero saturation, changing hue does not change the visible color.
- At zero or 100% lightness, the result is black or white regardless of hue.
- HSL lightness is not a reliable measure of perceived brightness or text contrast.
- HSL describes colors in sRGB and does not directly provide the wider gamut available through some newer color functions.
- Relative color syntax has different browser support requirements from traditional HSL syntax.
For example, this is valid:
color: hsl(210 80% 45% / 50%);
The following is invalid because it mixes commas and spaces:
color: hsl(210, 80% 45%);
The following is invalid because the legacy syntax requires percentages for saturation and lightness:
color: hsl(210, 80, 45);
Use one consistent syntax and the appropriate component types.
Browser Support
The CSS hsl() function is Baseline Widely available. The core function has been supported across major browser engines since July 2015.
Traditional HSL syntax works in current versions of Chrome, Edge, Firefox, Safari, and other modern browsers.
Modern space-separated syntax, missing components, and relative color syntax were introduced separately and may have different compatibility requirements in older browsers.
For example:
.box {
background-color: hsl(210 80% 45%);
}
For older browsers, the legacy comma-separated syntax remains useful:
.box {
background-color: hsl(210, 80%, 45%);
}
For current compatibility information, visit Can I Use? . Check relative color syntax separately when using hsl(from ...).
Specifications
The hsl() function is defined in the CSS Color Module Level 4 .
Relative HSL color syntax is defined in the CSS Color Module Level 5 .
These specifications define HSL color components, alpha values, modern and legacy syntax, missing components, and relative color calculations.
Related CSS functions include rgb(), hwb(), lab(), lch(), oklch(), and color-mix().
