Applying Grayscale Using CSS Filters

This technique has been around for a while, but it’s powerful and worth sharing. Using the filter CSS property you can apply visual effects to your elements, including the grayscale we’ll be discussing here. For my CV I wanted my image muted most of the time, but pop when it becomes the focus of the viewer (ie. they mouse over it), so I used a filter to apply grayscale by default and remove grayscale on hover. This article will explain how to do this technique.

How do it…

To start choose markup or an image that should be grayscaled. I will use the following image for this demo:


Next define your CSS:

.grayscale {
    filter: url(../files/filters.svg#grayscale); /* Firefox 3.5+ */
    filter: gray; /* IE6-9 */
    -webkit-filter: grayscale(1); /* Google Chrome, Safari 6+ & Opera 15+ */

.grayscale-hover:hover {
    filter: none;
    -webkit-filter: grayscale(0);

For FireFox, we also need to define the SVG filter file:

<svg xmlns="">
 <filter id="grayscale">
  <feColorMatrix type="matrix" values="0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"/>

For FireFox, instead of a separate file, you can also use a data-uri:

filter: url("data:image/svg+xml;utf8,<svg xmlns=\'\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");

Here is the image with the new CSS applied:


How it works…

The filter property[1] is still experimental and only implemented fully in webkit browsers with the webkit- prefix. FireFox and IE 10+ supports only the url(…); value, which can reference a filter.svg file to define any number of filters using the SVG filter element[2]. IE 6-9 implemented a non-standard filter property. For browsers properly supporting the filter property, the following values may be used: blur, brightness, contrast, drop-shadow, grayscale, hue-rotate, invert, opacity, saturate, sepia, and url[3].

So for Chrome, Safari, and Opera, we use the property -webkit-filter with the grayscale(N) value set, where N ranges from 0 to 1, indicating how much to gray the content. For IE 6-9 we use the non-standard gray value and none to remove the graying. Also, IE 6 does not support the hover pseudo-class for non-anchor elements, so deal with that how you will (I choose to ignore it). For FireFox we define what grayscale means using the SVG feColorMatrix filter and also none to remove the filtering.

Unfortunately, in IE 10 Microsoft decided to remove legacy filters and not implement the working standard, so this technique does not work in IE 10+. My take is to just ignore IE 10+ users, because supporting them is not worth the effort, but there are three solutions to support them: using an inline SVG element[4], applying grayscale to the image using a photo editor and swapping images on hover, or changing compatibility mode back to IE 9. Not of them are great solutions, but I think making two images is probably the simplest. If you choose to change the compatibility mode, here is the markup (keep in mind you may loose IE 10+ features by using this):

<meta http-equiv="X-UA-Compatible" content="IE=9">


  1. filter – css | MDN
  2. SVG filter element
  3. Filter Effects 1.0
  4. Grayscale JSFiddle by Karl Horky