Replicating Preprocessor Color Functions with Plain Old CSS
Karen Menezes on July 17, 2019I was ruminating on Sass’ lighten and darken functions today morning and wondered whether there was a way to do this via native CSS. I also remembered that I haven’t ever used HSL to define colors in my stylesheets and wondered whether this was the solution. I generally use the hexadecimal notation and also RGBA aplenty when I need to alter the transparency of a color.
However, HSL and HSLA have landed up being the revelations of today’s morning. It’s close to midnight and I’m close to being done with this article. And I’m definitely considering using them to define colors in future projects.
Let’s do a quick recap on colors in CSS to get some foundation:
There are 4 ways to declare a color in your CSS stylesheet:
color name
E.g. black, olive, firebrick
It’s good to check browser compatibility, although modern browsers support a whole slew of keywords for color names.
See the W3 spec for basic color keywords and for extended color keywords, which are supported by modern browsers.
#RRGGBB or #RGB
E.g. black is #000000, olive is #808000, firebrick is #b22222
Possibly the most common way to declare colors in CSS. Consists of a # character generally followed by 6 characters, where each pair represents the red, green and blue value. Uses numbers 0 – 9 and letters A to F to represent the color.
However, there is a 3 character shorthand form, which can be used when each pair consists of the same digit.
E.g. Black can be written as #000 instead of #000000 and red as #f00 instead of #ff0000.
rgb(r, g, b) or rgb(%, %, %)
Expresses a red, green and blue component, each generally within the range of 0 – 255 or percentages between 0 – 100%.
E.g. RGB with parameters in integers:
Black is rgb(0,0,0), olive is rgb(128,128,0), firebrick is rgb(178,34,34)
E.g. RGB with parameters in percentages:
Black is rgb(0%,0%,0%), olive is rgb(50%,50%,0%), firebrick is rgb(70%, 13%, 13%)
hsl(hue, saturation, lightness)
E.g. black is hsl(0, 0%, 0%) , olive is hsl(60, 100%, 25%), firebrick is hsl(0, 68%, 42%)
Check out this color wheel. Think of it as a pretty rainbow circle and you’ll never forget it.
Let’s look at the three parameters of hsl:
Hue, the first parameter is simply an angle measured in degrees on the color wheel.
0 degrees represents red
Isn’t that sweet and simple?
Hue is represented by an integer.
Saturation, the second parameter is represented by a percentage between 0 and 100, where 0 is some variant of grey/black and 100% is full saturation of the color.
Lightness, the third parameter is represented by a percentage between 0 and 100, where 0 is black and the darkest, 100% is white and the lightest and 50% is average.
This post doesn’t go into the details of the alpha channel, because if you are familiar with RGBA, HSLA follows the same principle, where the last parameter declares how transparent the color is, and even allows a float value (decimals) between 0 and 1.
Let’s mess around with HSL now:
Look at the color wheel again:
I want red #f00 represented as hsl:
color: hsl(0%, 100%, 50%)
0 corresponds to the hue, 100% is full saturation and 50% is an average.
I want firebrick #b22222 represented as hsl:
color: hsl(0, 68%, 42%);
As you see, the hue is still red, but the saturation and lightness are both reduced.
It just makes sense.
What’s so cool about HSL?
- - Well, for starters I can look at the color wheel and figure out the color I want. It looks pretty intuitive to me.
- - It should be pretty easy to get a contrasting color by just looking at the color wheel to see the degree on the opposite side.
- - I can adjust the shade of the color, and I can’t do this any other way in CSS. I can replicate some preprocessor color functions.
Hence, I could potentially lighten, darken, increase or decrease saturation, adjust hues and provide a contrasting color quite easily.
Let’s look at some basic Sass color functions and ways to replicate this with native CSS.
Our basic example contains no variables and uses the firebrick color, whose HSL is (0, 68%, 42%) and HEX value is #b22222.
Firebrick color
Default Firebrick color
Lighten firebrick by 10%
Sass: lighten(#b22222, 10%)
CSS: hsl(0, 68%, 52%)
Both result in #d83131
The CSS way simply increases the percentage of lightness, i.e. the third parameter of HSL by 10.
Darken firebrick by 10%
CSS: hsl(0, 68%, 32%)
Sass: darken(#b22222, 10%)
Both result in #891a1a
The CSS way decreases the percentage of lightness, i.e. the third parameter of HSL by 10.
Saturate firebrick by 10%
CSS: hsl(0, 78%, 42%)
Sass: saturate(#b22222, 10%)
Both result in #bf1818
The CSS way increases the percentage of saturation, i.e. the second parameter of HSL by 10
Desaturate firebrick by 10%
CSS: hsl(0, 58%, 42%)
Sass: desaturate(#b22222, 10%)
Both result in #a92d2d
The CSS way decreases the percentage of saturation, i.e. the second parameter of HSL by 10
Adjust the hue by 10%
CSS: hsl(10, 68%, 42%) Sass: adjust-hue(#b22222, 10%);
Both result in #b43b22
The CSS way alters the hue degree, i.e. the first parameter of HSL by 10.
So the next time you use a pre-processor to carry out some manipulations on your colors, remember you can do some of it with good ol’ CSS, the HSL way :)
Conclusion
I’m considering moving to HSL for upcoming projects, especially if they don’t need IE8 support.
If you wish to use HSL and HSLA, do keep in mind:
- - Declare a fallback color if you need to support certain browsers where support is unknown. See caniuse.com for more.
- - Photoshop has something called HSB (Hue Saturation Brightness), which does not correspond to HSL.
Here are some good solutions to this:
1. Check the amazing https://rgb.to/. Seriously, this website is the bomb and converts virtually anything to anything. I love it.
2. Declare the colors as you wish and then fire up dev tools in Chrome. Click the floral looking gear icon and under elements in General settings, show the color format as HSL. Then you can inspect element and get your HSL values for colors.