Color overlay filter proposal


Lately I’ve been needing a filter similar to Photoshop’s own layer styles/blending options. My question is if something like this is achievable with the current state of most browsers’ rendering engines.

The following images are an example of how Photoshop handles this:

Without color overlay:

With color overlay:

As far as I understand, CSS blending modes aren’t able to achieve this sort of behavior, and syntax-wise I’m thinking that something like filter: color-overlay(#ff0000) should be enough.

This is just a pretty lighweight proposal but if there’s enough attention to this post, and seems achievable, I’ll try and write a full spec for it.


So it takes an image and changes the RGB value of the non-transparent pixels to match the given input?


Yes, basically, but my idea is to use it for other elements as well, not only images.


It should be possible to do this today using a custom defined SVG filter, referenced from CSS.

<svg …>
  <filter id="color-overlay">
    <feFlood flood-color="red"/>
    <feBlend in2="SourceAlpha"/>
element {
  filter: url(#color-overlay);

If you want to propose this as a CSS filter shorthand, the first step would be defining it via SVG <filter>, like the currently-implemented ones.


I’m not that familiar with svg filters so I tried this one out verbatim and it didn’t seem to work on a image element with transparency. I haven’t been able to find a working alternative either.


Ah, fair enough. Here’s a working CodePen (except Safari, can’t figure out why right now):

If you wanted to define the filter solely in CSS, you could use a data: URI created with a preprocessor. Here’s a (naïve*) example for Sass:

@function color-overlay($color) {
  @return 'url("' + 
    "data:image/svg+xml,%3Csvg xmlns=''%3E\
%3Cfilter id='f'%3E\
%3CfeFlood flood-color='#{$color}'/%3E\
%3CfeComposite in2='SourceAlpha' operator='atop'/%3E\
%3C/svg%3E#f" + '")';

(Escaped \ line breaks added for readability on Discourse. Browsers won’t tolerate them.)

If you need Safari support today, chaining the filter shorthands might work — something like filter: sepia(100%) hue-rotate({some amount});.

* You would need to URL-encode the $color argument.


Awesome, thank you that works great!

I do also think that this sort of effect deserves to get its own filter shorthand (iOS for example has a first class image property called tintColor that produces the same effect).