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

CSS Interview Questions

Lately, I have been interviewing many engineers who are interested in a CSS contractor position, and am thoroughly disheartened by the number of candidates who put CSS expert on their resume, but don’ even know the basics of CSS. This article will discuss the ten questions I usually ask, including the answer and why I ask the question. My hope is not to just give the answer, but to educate as well.


Each question ...

Using PhantomCSS for Regression Testing Your CSS

I finally had a chance to play with PhantomCSS, a CSS regression testing tool that compares screenshots to see if CSS changes have affected the design, and wanted to share my experience with you. We are using it at Ariba to validate that I do not break any designs as I migrate us from two giant, unmanageable CSS files into smaller, modularize and better written lessCSS files. PhantomCSS uses

Rotating Multi-State Button

One of the designers at Ariba, recently came up with a design that needed a tri-state button to govern toggling some content. We came up with an interesting solution where the button has three colors on the outside, with the bottom color governing the content being shown. I am not sure if the widget will survive a usability study, but I put together a proof of concept using HTML 5 technologies and wanted to share ...

CSS Tip - Overriding CSS 3 Pseudo-Classes

While using CSS 3 pseudo-classes I ran into situations where I needed to programatically disable/change styles that were auto applied by the browsers. Todays article explains how to override styles applied by pseudo-class.

Getting ready

Two new and useful pseudo-classes introduced in the HTML 5 compliant browsers are :invalid and :valid. The styles set to these pseudo-classes are applied when various HTML 5 input attributes are processed. Assume the following CSS, which applies a red ...

Using Data URIs

After reading Nicolas Zakas article, Data URIs make CSS sprites obsolete, I was inspired to see how easy it would be to put into practice. His CSSEmbed JAR uses Base64 encoding for data URIs and MHTML to be backwards compatible with IE 6 and 7. So the logical step was to create a build script that runs CSSEmbed against all my CSS files.

Getting ready

You will need to install a copy of ...

Simple JavaScript Function To Include CSS

This article explains how to write a simple JavaScript function to include CSS files and notify when the loading of the file is complete. The issue is that most browsers do not fire a load event when the link element finishes processing the included CSS rules. And while many libraries have mechanisms for notifying when the CSS is included, I believe this technique is lighter and more elegant. A special thanks goes out to the ...

Dynamically Updating Content Of FireFox Ellipsis Hack

Some time ago, Justin Maxwell wrote an article (String Truncation With Ellipsis) explaining a CSS-only solution for applying ellipsis to the text inside of an HTML element. Unfortunately, to this day, FireFox does not support an ellipsis CSS rule natively; an XML hack is required for it to work in FireFox. However, this hack prevents you from being able to update the content of the node in JavaScript using the innerHTML property. The ...

CSS Targeted Only to the IPhone

One of this blogs readers, Dan Humphrey, was helpful enough to let me know that the footer position, in the new design, was not behaving correctly on the iPhone. Sure enough, when scrolling in Safari on the iPhone a position:fixed element behaves like an absolutely positioned element in other browsers. I like the fixed header and footer, and do not want to remove them, but at the same time, I dont want my site looking ...

CSS String Truncation with Ellipsis

Today’s article is brought to us by guest writer, Justin Maxwell. Justin will explain the technique he fine tuned for to ellipsis text using just CSS. For more information about ...