Recently I had to change the color of a white image. Since this image was rendered by a library, which did not allow replacing it by another one, it had to be done with CSS. Although there is a relatively simple solution to it, it proved to be quite a challenge to come up with that.
Lets get to it.
Should be easy!
Just add a hue-rotate
filter, that should work.
But it doesn’t. Of course not, that would be too easy. The image is still white.
Why didn’t it work?
After checking a few times if the filter really was applied, it dawned upon me.
White has a luminocity value of 100%, so changing the hue won’t do anything. In fact, white has a hue value of 0, which is red. So I should have known beforehand that changing the hue won’t work, silly me!
Change the luminosity then
Since 100% luminocity is white, and 0% is black, 50% should result in a rich color. Lets try that.
Changing the luminocity can be achieved by the brightness
filter, which changes the brightness based on the given factor.
Okay, something changed, that’s good. But the result is not as expected. There is no color. The image is just gray.
What happened?
The luminocity is now 50%, as expected. But I forgot about the saturation. Since white has 100% luminocity, I thought that saturation would also be 100%. Unfortunately, it is 0%, which causes the gray color.
So change the saturation
If there is a brightness
filter, there surely is a saturate
filter. And yes, there is!
Lets set the saturation to 100% then:
Again, nothing changed.
Turns out, the saturate
filter works the same way as the brightness
filter. It just changes the value based on the given factor. Now that’s a problem. As primary school math taught us, everything times 0
is 0
.
This makes the saturate
filter useless for this purpose.
Time to give up?
Not yet! There are a few other filters to try. Lets go through them:
-
blur
: obviously doesn’t change the color -
contrast
: does nothing in a gray image -
drop-shadow
: also doesn’t change the color -
grayscale
: well, can’t make a gray image gray_er_ -
hue-rotate
: the whole point is to make the hue visible, a different hue won’t change anything -
invert
: inverting gray, sadly, just results in a different variation of gray -
opacity
: it would be possible to make another color shine through, but that’s not what I’m after -
sepia
: that’s the last one. And finally, it looks like it could work!
The MDN documentation example looks very promising.
Let’s try it out:
Did that change something? It looks like white. Almost. By checking with the color picker I found out that the actual color is hsl(60, 100%, 97%)
.
That means, we’ve got saturation! Finally some results 🎉
From there it is now possible to apply the other filters to achieve the desired result.
Lets see some color!
I have written enough about trial and error already. Let me save you some time and show you how to get a pure red:
In my opinion this is the easiest color to work from to get whatever color you want.
For example, to get green, just add a hue-rotate(120deg)
at the end.
Wrapping up
White is a nasty color to change with filters. With the typical filters, it is impossible to create a color other than grayscale.
The sepia
filter might not have been designed for this purpose, but it saves the day!
One more thing: black
To turn black into a color, turn it to white and work from there:
img {
filter: invert(1) brightness(50%) sepia(100%) saturate(10000%);
}
Follow me on Twitter for more of my thoughts, articles, projects and work.
Top comments (1)
Thanks king. I feel lucky to have found this. It's a pity CSS doesn't have dedicated methods to do that.