Convert an image to grayscale in HTML/CSS

2018-12-31 10:11发布

Is there a simple way to display a color bitmap in grayscale with just HTML/CSS?

It doesn't need to be IE-compatible (and I imagine it won't be) -- if it works in FF3 and/or Sf3, that's good enough for me.

I know I can do it with both SVG and Canvas, but that seems like a lot of work right now.

Is there a truly lazy person's way to do this?

26条回答
姐姐魅力值爆表
2楼-- · 2018-12-31 10:53
img {
    -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
    filter: grayscale(100%);
}
查看更多
泛滥B
3楼-- · 2018-12-31 10:54

For Firefox you don't need to create a filter.svg file, you can use data URI scheme.

Taking up the css code of the first answer gives:

filter: url("data:image/svg+xml;utf8,<svg%20xmlns='http://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"); /* Firefox 3.5+ */
filter: grayscale(100%); /* Current draft standard */
-webkit-filter: grayscale(100%); /* New WebKit */
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%); 
-o-filter: grayscale(100%);
filter: gray; /* IE6+ */

Take care to replace "utf-8" string by your file encoding.

This method should be faster than the other because the browser will not need to do a second HTTP request.

查看更多
旧人旧事旧时光
4楼-- · 2018-12-31 10:54

Doesn't look like it's possible (yet), even with CSS3 or proprietary -webkit- or -moz- CSS properties.

However, I did find this post from last June that used SVG filters on HTML. Not available in any current browser (the demo hinted at a custom WebKit build), but very impressive as a proof of concept.

查看更多
栀子花@的思念
5楼-- · 2018-12-31 10:55

A new way to do this has been available for some time now on modern browsers.

background-blend-mode allows you to get some interesting effects, and one of them is grayscale conversion

The value luminosity , set on a white background, allows it. (hover to see it in gray)

.test {
  width: 300px;
  height: 200px;
    background: url("http://placekitten.com/1000/750"), white; 
    background-size: cover;
}

.test:hover {
    background-blend-mode: luminosity;
}
<div class="test"></div>

The luminosity is taken from the image, the color is taken from the background. Since it is always white, there is no color.

But it allows much more.

You can animate the effect setting 3 layers. The first one will be the image, and the second will be a white-black gradient. If you apply a multiply blend mode on this, you will get a white result as before on the white part, but the original image on the black part (multiply by white gives white, multiplying by black has no effect.)

On the white part of the gradient, you get the same effect as before. On the black part of the gradient, you are blending the image over itself, and the result is the unmodified image.

Now, all that is needed is to move the gradient to get this effect dynamic: (hover to see it in color)

div {
    width: 600px;
    height: 400px;
}

.test {
    background: url("http://placekitten.com/1000/750"), 
linear-gradient(0deg, white 33%, black 66%), url("http://placekitten.com/1000/750"); 
    background-position: 0px 0px, 0px 0%, 0px 0px;
    background-size: cover, 100% 300%, cover;
    background-blend-mode: luminosity, multiply;
    transition: all 2s;
}

.test:hover {
    background-position: 0px 0px, 0px 66%, 0px 0px;
}
<div class="test"></div>

reference

compatibility matrix

查看更多
明月照影归
6楼-- · 2018-12-31 10:57

Following on from brillout.com's answer, and also Roman Nurik's answer, and relaxing somewhat the the 'no SVG' requirement, you can desaturate images in Firefox using only a single SVG file and some CSS.

Your SVG file will look like this:

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1"
     baseProfile="full"
     xmlns="http://www.w3.org/2000/svg">
    <filter id="desaturate">
        <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>

Save that as resources.svg, it can be reused from now on for any image you want to change to greyscale.

In your CSS you reference the filter using the Firefox specific filter property:

.target {
    filter: url(resources.svg#desaturate);
}

Add the MS proprietary ones too if you feel like it, apply that class to any image you want to convert to greyscale (works in Firefox >3.5, IE8).

edit: Here's a nice blog post which describes using the new CSS3 filter property in SalmanPK's answer in concert with the SVG approach described here. Using that approach you'd end up with something like:

img.desaturate{
    filter: gray; /* IE */
    -webkit-filter: grayscale(1); /* Old WebKit */
    -webkit-filter: grayscale(100%); /* New WebKit */
    filter: url(resources.svg#desaturate); /* older Firefox */
    filter: grayscale(100%); /* Current draft standard */
}

Further browser support info here.

查看更多
孤独寂梦人
7楼-- · 2018-12-31 10:58

If you, or someone else facing a similar problem in future are open to PHP. (I know you said HTML/CSS, but maybe you are already using PHP in the backend) Here is a PHP solution:

I got it from the PHP GD library and added some variable to automate the process...

<?php
$img = @imagecreatefromgif("php.gif");

if ($img) $img_height = imagesy($img);
if ($img) $img_width = imagesx($img);

// Create image instances
$dest = imagecreatefromgif('php.gif');
$src = imagecreatefromgif('php.gif');

// Copy and merge - Gray = 20%
imagecopymergegray($dest, $src, 0, 0, 0, 0, $img_width, $img_height, 20);

// Output and free from memory
header('Content-Type: image/gif');
imagegif($dest);

imagedestroy($dest);
imagedestroy($src);

?>
查看更多
登录 后发表回答