2018-06-17 ~ 2 min

Coloring white Images with CSS filter

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.

See the Pen Hue Rotate by Dominik Weber (@domysee) on CodePen.

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.

See the Pen Brightness by Dominik Weber (@domysee) on CodePen.

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:

See the Pen Brightness Saturate by Dominik Weber (@domysee) on CodePen.

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

: obviously doesn't change the color contrast : does nothing in a gray image

: does nothing in a gray image drop-shadow : also doesn't change the color

: also doesn't change the color grayscale : well, can't make a gray image grayer

: well, can't make a gray image grayer hue-rotate : the whole point is to make the hue visible, a different hue won't change anything

: 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

: 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

: 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:

See the Pen Sepia by Dominik Weber (@domysee) on CodePen.

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 :tada:

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:

See the Pen Red by Dominik Weber (@domysee) on CodePen.

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% ) ; }