How to Turn Web Images to Grayscale (3 Ways)
I’ve always been a fan of grayscale images as I think they look more artistic. Many photo editors such as Photoshop let you turn colorful images into grayscale easily. There is even the option to tune the color depth and color tones. Unfortunately, it is less straightforward to do so on the Web due to the differences in browser capabilities.
In this post, we are going to walk through some methods that we can use to turn images grayscale. We’ll also look into the stumbling blocks of each method and near the end, we will combine these methods to achieve a grayscale image that works across different browsers.
Recommended reading: Image Adjustment With CSS Filter Effects
1. CSS Filter
Using CSS filter
property is perhaps the easiest way to turn image into grayscale. Back in the old day, Internet Explorer has a proprietary CSS property called filter
to apply custom effect including Grayscale.
Today, filter
property is part of CSS3 specification, and supported in some browsers, like Firefox, Chrome and Safari. Previously, we have also mentioned about the Webkit filter that allows us not only to turn images grayscale but also apply sepia and blur effect.
We can add the following style rules to turn images grayscale with the filter
property.
img { -webkit-filter: grayscale(1); /* Webkit */ filter: gray; /* IE6-9 */ filter: grayscale(1); /* W3C */ }
This code will take effect in IE6-9 and Webkit browsers (Chrome 18+, Safari 6.0+, and Opera 15+).
(Note: IE10 dropped support for the legacy IE filter
nor it also support for the prefixed version, -ms-filter
, for applying grayscale. This code does not work in Firefox either.)
2. JavaScript
The second alternative is by using JavaScript, which technically should work in all browsers that have JavaScript enabled, including IE6 and below.
var imgObj = document.getElementById('js-image'); function gray(imgObj) { var canvas = document.createElement('canvas'); var canvasContext = canvas.getContext('2d'); var imgW = imgObj.width; var imgH = imgObj.height; canvas.width = imgW; canvas.height = imgH; canvasContext.drawImage(imgObj, 0, 0); var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH); 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; } } canvasContext.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height); return canvas.toDataURL(); } imgObj.src = gray(imgObj);
Using JavaScript method, we will be able to apply the Grayscale effect upon certain condition, such as when the image is on hover
or being clicked. We can also use it along with jQuery effects to apply smooth animation when the image is transitioning from gray to full-color. The only downside that I can see from using JavaScript is that the effect will be discarded when JavaScript is disabled on the browser.
3. SVG
Another way is by using an SVG Filter.
All you need to do is create an SVG file, and put the following codes in it. Save and name the file to e.g. gray.svg
.
<svg xmlns="https://www.w3.org/2000/svg"> <filter id="grayscale"> <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>
Then, using the filter
property, we link the SVG file followed by the ID of the filter element in our SVG file:
img { filter: url('img/gray.svg#grayscale'); }
You can also embed the codes directly within the CSS, like so.
img { filter: url('url("data:image/svg+xml;utf8,<svg%20xmlns='https://www.w3.org/2000/svg'><filter%20id='grayscale'><feColorMatrix%20type='matrix'%20values='0.3333%200.3333%200.3333%200%200%200.3333%200.3333%200.3333%200%200%200.3333%200.3333%200.3333%200%200%200%200%200%201%200'/></filter></svg>#grayscale");') }
This will return the same result.
Conclusion
To have cross-browser support for the grayscale effect, we can put the abovementioned methods together, using the following code snippet. This code will apply the grayscale effect in Firefox 3.5+, Opera 15+, Safari, Chrome, and Internet Explorer.
img { -webkit-filter: grayscale(100%); -webkit-filter: grayscale(1); filter: grayscale(100%); filter: url('../img/gray.svg#grayscale'); filter: gray; }
We can utilize the above code along with the JavaScript method, and only provide CSS filter
as the fallback in case JavaScript is disabled. This idea can easily be achieved with the help of Modernizr.
Modernizr will add js
class in the body
, if JavaScript is enabled, and it will switch the class name to no-js
if it is disabled. With CSS, you can do the following.
.no-js img { -webkit-filter: grayscale(100%); -webkit-filter: grayscale(1); filter: grayscale(100%); filter: url('../img/gray.svg#grayscale'); filter: gray; }
That’s all, you can see the demo in action below:
Sources
Head over to the following sources for references on Grayscale and filter
effect:
- Filter Effect — W3C
- Understanding CSS Filter Effects — HTML5 Rocks
- Convert an image to grayscale in HTML/CSS — StackOverFlow
- CSS Filters Browser Support — CanIUse.com
- Mozilla CSS Filter — MDN
- Internet Explorer Fitler and Transition — MSDN