demosthenes.info

I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my other blogs

Massive Head Canon: Intelligent discussion of movies, books, games, and technology.

my projects

A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

Lena Söderberg full colorLena Söderberg desaturated with CSS

Convert Images To Black And White With CSS

css / filters

Estimated reading time: 2 minutes, 37 seconds

Filters allow us to visually process an image in the browser without needing to go through or use cycle-intensive, script-heavy methods in or PHP. are broadly supported in modern browsers, and we can gain support in older versions and alternative browsers – even IE –  by using a combination of techniques.

In this article we’ll convert an image to black & white with pure CSS using the classic test image of Lena Söderberg. In other articles in this series I discuss how to achieve sepia toning, blurring, and other visual effects.

The CSS greyscale filter

Desaturating a color image couldn’t be simpler with CSS. We’ll apply the filter as a class, as you will typically want several images to be affected by the code at the same time:

img.desaturate {
	filter: grayscale(100%);
}

Chrome and Safari still implement CSS filters via vendor prefixes, so we need to add a declaration for those:

img.desaturate { 
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
}

Applying the class to the image is easy:

<img src="lena-söderberg.png" alt="Lena Söderberg" style="width: 512px; height: 512px;" class="desaturate">

Add An SVG Filter Effect

The CSS shown to this point works in Chrome 18+, Safari 6 and higher on both mobile and desktop platforms, Firefox 35+, Opera 15+, and the latest browser versions for Android and Blackberry; IE support is in development.

To gain the same effect in earlier versions of Firefox, we need to use an filter, which I’ll create as a separate document named desaturate.svg. The code for that file will be:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<filter id="greyscale">
<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>

If the SVG code looks slightly daunting – and the matrix math behind it is somewhat complex – don’t worry. This is one piece of code that I’d actually encourage you to copy and paste as a generic “recipe”. I’ll explain matrix transformations in a future article.

With the SVG file saved beside our page and test image, we will extend the CSS to become:

img.desaturate{
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
filter: url(desaturate.svg#greyscale);
}

Add Support for IE

To cover IE 6 – 9, we'll apply Microsoft’s simple but proprietary use of filter:

img.desaturate{
-webkit-filter: grayscale(100%);
filter: gray; filter: grayscale(100%);
filter: url(desaturate.svg#greyscale);
}

If you want to add in support for stiill older versions of Webkit:

img.desaturate{
-webkit-filter: grayscale(1); -webkit-filter: grayscale(100%);
filter: gray; filter: grayscale(100%);
filter: url(desaturate.svg#greyscale);
}

The CSS we've written here allows us to visually convert an image to black and white on the fly in our browser, with no need to save new versions in PhotoShop. Using CSS also makes the image much easier to modify: for example, you’ll see that lowering the percentage used in our declaration from 100% to 50% causes a visual blend of the desaturation effect with the original color image.

Update

A slightly easier approach inlines the SVG into the CSS directly, removing the need for any SVG code in the <body>:

img.desaturate{
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
filter: gray;
filter: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' height='0'><filter id='greyscale'><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>#greyscale");
}
Play with this code on CodePen
comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.