Black and White CSS Hover

We’ve used various versions of jQuery and HTML5 to get Back and White images with hover. Here’s our preferred solution

<script type="text/javascript">// <![CDATA[
// Greayscale Images
	// On window load. This waits until images have loaded which is essential

		// Fade in images so there isn't a color "pop" document load and then on window load
		jQuery(".item img").fadeIn(500);

		// clone image
		jQuery('.item img').each(function(){
			var el = jQuery(this);

<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 = jQuery(this);
			this.src = grayscale(this.src);

		// Fade image 
		jQuery('.item img').mouseover(function(){
			jQuery(this).parent().find('img:first').stop().animate({opacity:1}, 1000);
			jQuery(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 = ([i] +[i + 1] +[i + 2]) / 3;[i] = avg;[i + 1] = avg;[i + 2] = avg; 			} 		} 		ctx.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height); 		return canvas.toDataURL();     }
// ]]></script>

{here we are adding greyscale to ‘.item img’ so replace with your own element}

… the problem with many of these approaches is that they break your preferred code structure. CSS would be a more elegant way of doing it and with some exclusions it is possible.

Black and White CSS Hover

.desaturate {
filter: grayscale(100%); /* Current draft standard */
filter: gray; /* IE */
-webkit-filter: grayscale(100%); /* New WebKit */
-webkit-filter: grayscale(1);  /* Older WebKit */
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: url(filters/desaturate.svg#greyscale); /* Firefox */
.desaturate:hover {
    filter: none;
    -webkit-filter: grayscale(0);

For this to work in Firefox you need to create the file ‘desaturate.svg’ and call it via the filter on the last line. Here’s a link to the desaturate.svg file (right click and save).


As far as we can see this doesn’t work on older Safari versions on mobile devices (such as my trusty iPad 1). If anyone knows how to plug this hole please do let me know!

About the Author
Black and White CSS Hover Black and White CSS Hover 0da77002febbfe28d15144a57bbcc2c9 s 180 d mm r g


A highly experienced Web Designer / Web Developer (Webflow, WordPress, Weebly & Custom), Front-end / Back-end Developer & New Media Specialist, with extensive knowledge of a wide spectrum of technologies in the Development and Creative Industries, built up over a number of years.