Once upon a time, grayscale image has to be manually converted in order to be displayed on the web. Now with HTML5 canvas, images can be manipulated into grayscale without having to use image editing software. I've put together a demo to show you how to use HTML5 & jQuery to dynamically clone color images into grayscale (see demo). Credits: thanks to Darcy Clarke (my Themify's partner) for the jQuery and Javascript code.
The Purpose
This demo is intented to show you how to make a grayscale/color image hover effect with HTML5 and jQuery. To achieve this effect before HTML5, two images are required: a color and a grayscale version. Now HTML 5 made it easier and faster because the grayscale image is generated from the original source. I hope you will find this script useful in your design such as portfolio showcase, photo gallery, etc.
jQuery Code
The jQuery code below will look for the target images and generate a grayscale version. When hovering the image, it will fade the grayscale image into color.
<script src="jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
// On window load. This waits until images have loaded which is essential
$(window).load(function(){
// Fade in images so there isn't a color "pop" document load and then on window load
$(".item img").fadeIn(500);
// clone image
$('.item img').each(function(){
var el = $(this);
el.css({"position":"absolute"}).wrap("<div class='img_wrapper' style='display: inline-block'>").clone().addClass('img_grayscale').css({"position":"absolute","z-index":"998","opacity":"0"}).insertBefore(el).queue(function(){
var el = $(this);
el.parent().css({"width":this.width,"height":this.height});
el.dequeue();
});
this.src = grayscale(this.src);
});
// Fade image
$('.item img').mouseover(function(){
$(this).parent().find('img:first').stop().animate({opacity:1}, 1000);
})
$('.img_grayscale').mouseout(function(){
$(this).stop().animate({opacity:0}, 1000);
});
});
// Grayscale w canvas method
function grayscale(src){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var imgObj = new Image();
imgObj.src = src;
canvas.width = imgObj.width;
canvas.height = imgObj.height;
ctx.drawImage(imgObj, 0, 0);
var imgPixels = ctx.getImageData(0, 0, canvas.width, canvas.height);
for(var y = 0; y < imgPixels.height; y++){
for(var x = 0; x < imgPixels.width; x++){
var i = (y * 4) * imgPixels.width + x * 4;
var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
imgPixels.data[i] = avg;
imgPixels.data[i + 1] = avg;
imgPixels.data[i + 2] = avg;
}
}
ctx.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
return canvas.toDataURL();
}
</script>
How to use it
To apply this to your site:
- include a copy of jquery.js
- paste the code as shown above
- set the target image (eg:
.post-img,img,.gallery img, etc.) - you may change the animation speed (ie. 1000 = 1 second)

Compatibility
It works with any browser that support HTML5 and Javascript such as Chrome, Safari, and Firefox. If HTML5 is not supported, it will fallback to original color image. Note: if it doesn't work with Firefox and Chrome locally. You need to put the HTML file on a web server.
Credits
The Javascript & HTML 5 grayscale is coded by Darcy Clarke.

Nice effect. Would be cool to if grayscale was applied to images before they were shown.
Nice technique! Thanks for sharing it. It can enhanced by applying grayscale to images before they were revealed.
Nice cant’t believe i have only just found this amazing site i like all your posts
thanx a lot.
Works really nice on my Firefox 3.6 MAC .. lovely demo
Can’t get this to work, pretty sure I did everything correctly was anyone else having issues with this?
That is cool man, really loved it.
thanks a ton for the tut ! ;)
i love this demo….
its really awesome.. :)
Thanks
I love the effect.
&Would definitely love to use it.
How ever, I’m not too familiar with javascript.
I’m using my offline xampp blog, and tried to add the script before the wp_head function…but it still doesn’t work.
the tutorial says use a copy of jquery…
i’m not sure if that means copy and pasty the jquery.js in the same folder or not?
Please help, cause I really really want to use this wonderful script :)
Updates: I copied the jquery.min.js content and pasted it into a new document.
By changing that I realized that the images turn grey but no effect when I rollover them….why might that be?
This is awesome, I was trying to do something like this using timThumb all last summer. Much easier and effective, thanks for sharing.
that’s not exactly true, it’s possible to create a grayscale (or duotone) copy of your image with PHP. ofcourse this means storing another physical image on your server, but there’s no manual action needed.
Woow! Amazing technique for image galleries! ;)
This is amazing. Great work.
One thing though: I haven’t looked too closely at the code, but it seems like you’re just averaging the RGB values. It would be more accurate to use a weighted average: Y = 0.2126 R + 0.7152 G + 0.0722 B – http://en.wikipedia.org/wiki/Luma_(video)
Amazing canvas technique.
But I would recommend to replace jQuery with CSS3 Transition method – so the post title may “Greyscale Image hover using HTML5 and CSS3″. Ofcourse, its not crossbrowser compatible, but yes its an experiment :)
wow! this look awesome!
think this could be tweaked to to show a sepia preview on a photographers’ proofing site?
Have tried everything, but still can’t get this to work. Can someone post the actual HTML code used to display the images on the page?
Very awesome effect, i’m use it on my sites, txh WebDesignerWall & Darcy Clarke
I think I’d use a webworker to generate grayscales. On slower machines and/or larger images, it may delay loading the page too much, and webworkers are non-blocking. They don’t work on all browsers, but the same is true for canvas, so I think it’ll be better in the end.
Especially when you go from the grayscale effect to a blur effect, which is much more cpu-intensive :)