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.

hello there…awesome tuts. can i re-post on my blog in my language? will credit to you
AWESOME! Exactly what I was looking for! Thanks a lot!
Doesn’t work on latest Chrome 10.0.634.0/Win7. Images don’t show up until you hover on them.
I have this effect on my portfolio site, using the pre-HTML5 technique. Looks like I’m due for an update! Awesome tut, thanks!
Thank you!!!! I was just looking for an effect like this to use in my soon-to-be-redesigned portfolio!!
Thank you thank you thank you! Exactly what I was after! :)
Works great on my XP / Chrome 8.0.552.237 – and I agree, it’s AWESOME!
Thanks for showing us this – I had never seen this jQuery trick explained before…
Nice article and thanks for sharing!
On mouseover and mouseout events, maybe the animate duration value should be decreased a bit?
This way you won’t have to wait so much (1000ms) to see the effect.
Can’t seem to get this to work. I tried to just run the demo on my site and the images get duplicated, one on top of the other, where the top one only appears when scrolled over. Any ideas?
That looks useful and the transition isn’t jarring.
Javascript errors in IE8
Thanks for this! I have just the use for it. :)
Expectacular efecto con las imagenes, creo que muy interesantes!!!
“Works great on my XP / Chrome 8.0.552.237″
Great sense of humor!
Wouldn’t it just be easier to do this with CSS?
Nice technique! But for less lines i might still do this with a simple sprite with b&w version / color version and a bit of CSS.
That’s a nice, subtle transition to colour too. Thanks for the article.
Really great technique. Thanks for sharing!
@Olli – It is possible with less lines but not only would it be more tedious creating the sprites in comparison to a single color image, the accumulated file sizes for the images would be greater than the technique used here. Basically, it would result in a higher file size over line count, impacting — though minimal — page load times.
Or you could use an svg filter without the need to tax the cpu (well if you had heaps of images) looping thru pixels.
nice
The animated effect is possible with this only not with CSS.
Yes, Javascript error in IE8.