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.

very very helpful and much appreciated, fits in well with any div layout, no need to adjust size of divs or images.
Is there a way to reverse it so the color displays at rest and when hovered over it turns gray? thanks awesome plugin
I’m using the same method on my service, I’m getting Uncaught Error: INDEX_SIZE_ERR DOM Exception 1, can any one help?
NB:- The error is only in chrome
I had the same error in chrome and safari.
I was calling the function in document.ready instead of $(window).load as it is in the example.
I changed that and it works fine now!
I removed CSS opacity to “0″ then working. But how to change Grayscale to Green colored scale ?
Is there a way to adjust the greyscale? It should be a bit lighter grey.
How can I adjust this??
how do i use this in tumblr?
I’m wondering the same… also, how do you reverse it? I want the coloured images to turn into a grayscale, like it happens on this Tumblr: http://4pologize.tumblr.com
Thanks for your work. Nice effect.
I’ve been implementing on a site I’m working on but when I was doing some testing for IE8 and 7 this didn’t work. I am using the HTML 5 shiv located here:
http://html5shiv.googlecode.com/svn/trunk/html5.js
…but this unfortunately doesn’t get it working.
Is there any intention of making this compatible with anything but latest gen browsers?
Thanks!
OMG! This is the must awesome image over script I ever seen! I cannot believe the transition of colors is in the code. I will definitely use this for my portfolio. Thanks a lot!
This works really well. Very impressive but has anyone noticed that it shifts the images 30 odd pixels to the right?
Im using it in conjunstion with a standard WP Gallery. I shall play about with the CSS in the JS I think
Awesome tutorial guys! This is the best implementation I’ve seen, along with very tight code. Cheers and thanks!
adsfjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
Could someone tell me why this moves my image over and down? I’m trying to implement this into my custom joomla template to a dynamically generated image tag. I have several images in a row and the first image is is pushed down and to the right. Any help would be appreciated!
If someone interested, I update the script for IE < 9,
replace :
this.src = grayscale(this.src);
by
// Brother version
var ua = $.browser;
// IE < 9 Brother
if ( ua.msie && ua.version.slice(0,3) < 9 ) {
el.css('filter',"progid:DXImageTransform.Microsoft.BasicImage(grayScale=1)");
}
// Canvas Brother
else {
this.src = grayscale(this.src);
}
Brilliant! I’ve been trying for hours to fix it in IE, and the you do it in such a simple fashion. Thanks.
Great! Many thanks for this awesome fix for IE7/IE8!! :-) It’s easy way!
Anyone figure out the pixel shift bug?
I had it in IE only – fixed it by adding:
position:relative;
left:0;
to the images.
I also had a pixel shift bug in Firefox 9 and IE 7 where the images were shifting right.
If using the exact script at the top of the page, on line 13 I changed:
el.css({“position”:”absolute”})
to
el.css({“position”:”relative”})
and my weird right shift was fixed.
Hello,
Great tutorial indeed. I’ve used this on a project to make all images grayscale when loaded and add color hover effect.
I bumped into a small bug though:
When you apply this script to images and one image fail to load, it breaks the whole code. As I understood it should be a imgObj.onload = function() {
before the ctx.drawImage() function so the page will wait until the images are loaded, but this just draws a transparent image.
Any thoughts?
Wow! Thanks!
David, thanks for the IE9 or less change to the script. I was trying myself and decided to look for the original post.
Thank you!
Thanks a bunch for this! Really like using this effect on websites it gives a site a really clean feel without having to use to many colours in thumbnails! Thanks
hi,
with firefox 10 there is a short black between grayscale/color transtion.
Here is a strange fix with background-color :
.clone().addClass(‘img_grayscale’).css({‘z-index’:’500′,’opacity’:’0′,’position’:'absolute’, ‘background-color’ : ‘#FFF’})
How do you tag your images for this to work?
//
Is that how?