CSS: change a transparent PNG to any color you want.

TL;DR

The trick is to drop a shadow on the PNG image, give the shadow the desired color and make sure the shadow is far away from the image. Finally, move the image out of view, just far enough for the shadow to move into view.

CSS:

.png-container {
  overflow: hidden;
}

.png-container img {  
  filter: drop-shadow(0px 100px 0 #118800);
  transform: translateY(-100px);
}

HTML:

<div class="png-container">
  <img src="my-logo.png">
</div>

With all the latest and greatest CSS changes that have made it to all major browsers in the last couple of years, you would think it’s trivial to change the color of the non-transparent parts of a Semi-transparent PNG image, with something like this:

filter: overlay-color('#118800');

Unfortunately, at the time of writing there’s no such CSS filter and the only solutions I found were either very complex (using a combination of multiple filters to get as close as possible to the desired color) or recommended using other image formats (SVG). I even suggested, many years ago, to use icon-fonts instead of PNG images.

Clearly, non of these solutions are satisfying.

I stumbled on another solution today, suggesting that you could use drop-shadow, and then set the opacity of the actual PNG to something like 50%.

filter: opacity(0.5) drop-shadow(0 0 0 blue);

This approach indeed allows us to set the shadow color to whatever we like, but the problem is that with opacity 1, the shadow is hidden by the actual PNG, and when we set opacity to 0, then there is nothing to cast the shadow.

This got me thinking, what if we could just keep the shadow and hide the image? But how? Hiding the image results in no shadow. Turns out that there’s another way to hide HTML elements that was heavily used before CSS included properties like visibility and opacity.

In the old days, elements where often hidden by simply moving them off-screen like this:

text-indent: -999999999px

Or like this:

position: absolute;
left: 100%;

These days, these tricks still work, but there’s a more modern way. So with a combination of 3 simple rules, we can get the desired effect.

  1. Make sure the overflow of the image container is set to hidden.
  2. Drop shadow on the PNG image and choose your color. Make sure the position of the shadow is far away so the shadow doesn’t overlap the image.
  3. Then transform the image by moving it so that only its shadow is visible in the image container.
.png-container {
  overflow: hidden;
}

.png-container img {  
  filter: drop-shadow(0px 100px 0 #118800);
  transform: translateY(-100px);
}

See the Pen Change PNG color with CSS by Jules Colle (@pwkip) on CodePen.