Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.
The CSS hsl()
function represents color in the sRGB color space and displays it according to its hue, saturation, and lightness. We provide a value for each of those three channels to produce a color.
.element {
color: hsl(90deg, 50%, 50%);
background-color: hsl(53deg 20% 10% / 0.4);
}
We can create shades of a color by changing the color’s saturation or lightness values. Like the rgb()
function, hsl()
works with colors in the sRGB color space, allowing us to pluck colors from that space using hue, saturation, and lightness to configure the color.
A color space is a specific range of colors that can be displayed, and it is based on a color model. Examples include sRGB, AdobeRGB, P3, and ProPhoto RGB. A color model, on the other hand, is the notation used to represent that color. So, HSL is a color model in the sRGB color space.
The hsl()
function is defined in the CSS Color Module Level 5 specification.
Syntax
hsl() = [ <legacy-hsl-syntax> | <modern-hsl-syntax> ]
<modern-hsl-syntax> = hsl(
[<hue> | none]
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[ / [<alpha-value> | none] ]? )
<legacy-hsl-syntax> = hsl( <hue>, <percentage>, <percentage>, <alpha-value>? )
No need to get into the historic details, but nowadays we can write hsl()
values in two ways:
- Legacy syntax: Comma-separated values, e.g
hsl(125deg, 25%, 40%)
- Modern syntax: Space-separated values, e.g
hsl(125deg 25% 40%)
Arguments
The function takes three arguments — one for the color’s hue, one for its saturation, and one for its lightness — and an optional fourth value that sets the color’s transparency.
/* numbers ranging from 0 - 360 for hue value */
.element {
color: hsl(200 20% 50%);
}
/* angles ranging from 0deg - 360deg for hue value */
.element {
color: hsl(40deg 3% 30%);
}
/* numbers ranging from 0 - 100 for S (saturation) and L (lightness) */
.element {
color: hsl(200deg 15 20);
}
/* percentages ranging from 0% - 100% for S (saturation) and L (lightness) */
.element {
color: hsl(120deg 30% 10%);
}
/* Optional fourth value for transparency */
.element {
color: hsl(53deg 20% 10% / 0.4);
color: hsl(10deg 20% 51% / 50%);
}
/* Using relative colors */
.element {
color: hsl(from green, 50deg s 50%);
}
Unlike rgb()
in which colors are defined through their redness, greenness, and blueness, hsl()
has a more readable syntax; we can pick a color via its hue, saturation, lighting, and an optional alpha value.
- Hue: A number or angle between
0deg
and360deg
that sets the base color. Angles are cyclic for each360deg
, so0deg
,360deg
,720deg
, etc. are the same, and going over360deg
is just like starting the hue from zero. - Saturation: A number (from 0 to 100) or percentage representing how much of the hue is in the color. For example, a pure red would be
100
or100%
saturated (hsl(0 100% 50%)
). Values above50
or50%
will approach the base color and below a greyscale. - Lightness: Sometimes called luminosity, this is a number (from 0 to 100) or percentage that sets the amount of white and black added to our base color. In pure red, the luminosity is set to
50%
. Values above will approach pure white, and below pure black. - Alpha: A number or decimal (from
0
to1
) or percentage representing the transparency of the color.
If the number or percentage falls below the threshold, it is evaluated to 0%
, and if it goes above the threshold, it evaluates to 100%
. The hue
value is the exception, which cycles through the color wheel in degrees, ranging 0
–360deg
.
hsl()
?
Why The hsl()
function is quite straightforward: provide it with only three values and we can represent any color in the sRGB color space. However, we choose it for more than its succinctness, especially compared to rgb()
or its hexadecimal form.
Think about how we usually perceive and communicate colors. Instead of saying “This color has 45 points of red more than this other color,” we say that “A color is lighter or more saturated than another,” the same way you can manipulate colors in hsl()
, making it a whole more human readable.
Apart from being harder to read, there is another problem with the usual rgb()
and hexadecimal form: maintenance.
Imagine three shades of red written in rgb()
with varying lightness:
/* base red color */
rgb(237, 70, 44)
/* lighter red color */
rgb(255, 120, 100)
/* darker red color */
rgb(200, 50, 30)
We can essentially create the same red with the hsl()
function’s hue and saturation channels, then use the lightness channel to create different shades of the same color. Notice in the following example how all three colors share the same first two arguments and we’re only adjusting the lightness to produce different shades of red:
/* base red color */
hsl(8, 84%, 55%)
/* lighter red color */
hsl(8, 84%, 70%)
/* darker red color */
hsl(8, 84%, 40%)
For a visual aid, you can also check out the demo below:
Hexadecimal color values (e.g. #ff0000
for red) is no different (and maybe even more tedious and confusing). As a web designer, changing one value is easier than changing three values in a function to get a desired color. And the more colors we have, the more tedious it becomes. Imagine changing 15 color variables to get a specific color gradient when five or fewer can be changed to obtain the same result.
With an even more extreme case, let’s say you want to be wacky and have 40 shades of red on your website but then decide to change them to blue. You have to perform 120 changes in rgb()
to get the colors you need when you could only change the hue to get the same result — that’s a third of the work!
That’s the beauty of the hsl()
CSS function. It’s easier to read and understand what the values are doing than other color functions and values that are based on color channels instead of hue, saturation, and lightness.
hsla()
It is the same thing as The hsl()
function and hsla()
function are essentially the same. The hsla()
function was designed to support alpha transparency, meaning we can make a color more or less transparent with a fourth value that configures it.
But in more recent years, the hsl()
function was updated to support a fourth value for alpha transparency. We specify the alpha transparency following a forward slash after the HSL arguments:
/* hsla() */
hsla(50 50% 50% / .5);
/* hsl() with alpha transparency */
hsl(50 50% 50% / .5)
As a result, there’s very little sense in using hsla()
since hsl()
is capable of the same thing. Use hsl()
if given the choice.
It supports the relative color syntax
The hsl()
function supports the relative color syntax, which means that we can use from <color>
directly in the function to convert one color into another. For example, let’s say you have a hwb()
color value:
.element {
color: hwb(10% 20% 50%);
}
But you want that color to be hsl()
instead. You go “from” that color and convert it into HSL channels:
.element {
color: hsl(from hwb(10% 20% 50%) h s 40%);
}
Notice that in the process of converting colors, I set the lightness channel to 40%
. That means we can take a color from another color space, convert it to HSL channels, and then manipulate the color by setting one of the HSL channels.
This is a great way to translate colors from different color spaces. For example, the lab()
CSS function operates in the CIELAB color space but can be translated to the sRGB color space to be used by the rgb()
, hsl()
or hwb()
functions.
A quick demo below shows the colors produced by the lab()
function inside the hsl()
function
.element {
background-color: hsl(lab(50% 50% 50%) h s l);
}
It supports math functions
You can use math functions in hsl()
to slightly change a color stored in a custom property:
.element {
background-color: hsl(
calc(var(--my-h-value) + 90deg) calc(var(--my-s-value) + 40) var(--my-l-value) / calc(var(--my-a-value) + 0.1)
);
}
It can even be used to change each channel after using the from <color>
syntax:
.element {
background-color: hsl(from lab(30% 50% 20%) calc(h + 20) calc(s + 40) l / 0.5);
}
In the example above, I’m using the calc()
function to add 20 more points to the h
channel and 40 more to the s
channel. Here’s what this looks like in the demo below:
Demo
This demo shows an example of a hue with varying lightness. It’s one of the powerful features I love about HSL — how easy it is to pick different shades of colors for your web application.
Here’s a cool demo showing the cool colors in HSL. Change the colors accurately via the input fields to generate a new background color and some confetti! Hope you have fun with this!
Specification
The hsl()
function is defined in the CSS Color Module Level 4 specification, while the relative syntax using channel keywords is defined in the CSS Color Module Level 5 specification.
Browser Support
The hsl()
color function can be used across all major browsers. It is a fully functional function that functions as intended without any issues so far. How’s that for a tongue twister?
More Information
- HSL Color Picker
- A Guide To Modern CSS Colors With RGB, HSL, HWB, LAB And LCH (Michelle Barker)
- CSS relative color syntax (Adam Argyle)
- OKLCH in CSS: why we moved from RGB and HSL (Andrey Sitnik & Travis Turner)
- Why CSS HSL Colors are Better! (Elad Shechter)