Set an SVG color overlay filter on an img

As part of the Wrestling layout I’m trying to mimic from the WhatCulture magazine I needed to have color overlays across all of the wrestler illustrated images.

Currently the CSS Filter property can do lots of things but the ability to put a color overlay isn’t part of that capability.

Side Note: why is that you can’t filter with color using the filter method in CSS? At the moment we can do blur(), brightness(), contrast(), even sepia() so why not color(#FFF) or color(0,0,0,0.25) to add the level of transparency too. Anyway, we can still do it, let’s see.

Creating the SVG Filter

I found a great article by Una Kravets on the subject where she looks at using the FEColorMatrix with SVG to create a series of colours that can then be used in the filter. https://alistapart.com/article/finessing-fecolormatrix

Una is far better at explaining the rationale behind the different options for creating the colours so to learn more about creating the SVG file go read that, but for now this is the file that I ended up with which covered all the SVG Filter colours that I needed including

  • Red
  • Blue
  • Green
  • Yellow
  • Magenta
  • Pink
  • Orange
  • Cyan

<svg xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink"  
     width="960px" 
     height="560px" 
     viewBox="0 0 960px 560px">

<!-- lacking the B & G channels (only R at 1) -->
<filter id="red">
  <feColorMatrix
    type="matrix"
    values="1   0   0   0   0
            0   0   0   0   0
            0   0   0   0   0
            0   0   0   1   0 "/>
</filter>

<!-- lacking the R & G channels (only B at 1) -->
<filter id="blue">
 <feColorMatrix
    type="matrix"
    values="0   0   0   0   0
            0   0   0   0   0
            0   0   1   0   0
            0   0   0   1   0 "/>
</filter>

<!-- lacking the R & B channels (only G at 1) -->
<filter id="green">
  <feColorMatrix
    type="matrix"
    values="0   0   0   0   0
            0   1   0   0   0
            0   0   0   0   0
            0   0   0   1   0 "/>
</filter>
	<!-- lacking the G channel (R and G at 1) -->
<filter id="yellow">
  <feColorMatrix
    type="matrix"
    values="1   0   0   0   0
            0   1   0   0   0
            0   0   0   0   0
            0   0   0   1   0 "/>
</filter>
<!-- lacking the G channels (mix of R & B)
Red + Blue = Magenta
-->
<filter id="magenta">
  <feColorMatrix
    type="matrix"
    values="1   0   0   0   0
            0   0   0   0   0
            0   0   0.5   0   0
            0   0   0   1   0 "/>
</filter>
	
<filter id="pink">
  <feColorMatrix
    type="matrix"
    values="1   0   0   0   0
            0   0   0   0   0
            0   0   1   0   0
            0   0   0   1   0 "/>
</filter>

<filter id="orange">
  <feColorMatrix
    type="matrix"
    values="1   0   0   0   0
            0   0.5   0   0   0
            0   0   0   0   0
            0   0   0   1   0 "/>
</filter>

<filter id="cyan">
  <feColorMatrix
    type="matrix"
    values="0   0   0   0   0
            0   1   0   0   0
            0   0   1   0   0
            0   0   0   1   0 "/>
</filter>
</svg>

If the grid of numbers is a little hard to understand don’t be alarmed, it took me a little while to wrap my head around what I was doing. In the end I set myself a couple of rules that seemed to work.

  1. Always leave the 4th Column set to 1, the alpha transparency. This is acting as a filter, not an overlay, so it will already be transparent.
  2. Don’t go into negative values. They confuse me more about the logistics of what number is being set against each RGB value. There is a tool below that helps with this though
  3. If you want to create a new colour, go to a tool like photoshop and get the colour picker. Choose a colour, and then look at the RGB values to help you set them. The values in PS go from 0-255, so I manipulated the colour so that the RGB colours were either 255, 191, 127, or 64 (which then equates to 1, 0.75, 0.5, 0.25) and set the table that way.

If you’re more visual with getting the filter you’re after and want to extend it into negative numbers and utilise more of the article from Una then check out the SVG Color Filter playground tool which allows you to upload an image and play with the color filter applied in the browser with live preview results.

Applying SVG filter to an IMG

Now that the SVG filter has been created and we’ve defined all of the different colors that we want to apply to the image we need to apply the actual filter.

The HTML I have for each of the wrestlers is


<figure class="wrestler-23 pink"><img src="wrestlers/23-Shaun-Michaels.jpg" alt="Shaun Michaels" />
<figcaption>Shaun Michaels</figcaption>
</figure>

where red is the filter color to be applied to the wrestler. Then the CSS That is applied for the images is below:


img {
	width: 100%;
	max-width: 100%;
	}
figure {
	margin: 0;
	padding: 0;
	overflow: hidden;
	}
	
.pink img {
	filter: url("/wrestling/colour-overlay.svg#pink");
	transition-duration: 3s;
	transition-property: filter;
	transition-timing-function: ease-in-out;
	}

img:hover {
	filter: none;
	}

I’m targeting the img tag that is a child of the .pink class that was applied to the figure element, then I’m applying a url() filter to that image with the SVG file that we created and referencing the #pink element.

I could apply the .pink class directly to the image itself as well, but this how I ended up coding it first time around (I may go back and change that later).

This code produces the following results:

Screen shot of the Wrestling layout from What Culture
Shaun Michaels with his Pink SVG Color filter applied via CSS

Subscribe to our Newsletter

Add your email address and receive an email every Friday covering off everything worth knowing about building your websites responsively.