在HTML / CSS中将图像转换为灰度


619

有没有一种简单的方法可以显示灰度的彩色位图HTML/CSS

它不需要与IE兼容(我想也不会)-如果它可以在FF3和/或Sf3中工作,对我来说已经足够了。

我知道我可以同时使用SVGCanvas和Canvas,但是目前看来这需要大量工作。

有没有真正懒惰的人做到这一点?


14
“它不需要与IE兼容(我想它不会)”自1997年(IE4)以来, IE就提供了一套DX过滤器 ,仅使用CSS即可完成此工作。现在,他们已经在IE10中删除了DX过滤器,并严格遵循基于SVG的标准过滤器。您可能想看看这个这个演示
vulcan raven 2012年

8
@vulcanraven并不是真正的CSS,如果在IE中禁用了活动脚本,过滤器将停止工作。
robertc

3
@robertc,那就是正确的。相反,如果在任何浏览器中禁用javascript,则几乎所有RIA(包括Stackoverflow)都将停止工作(除非Web开发人员已实施仅HTML版本的后备广告)。
vulcan raven 2012年

2
只需使用CSS stackoverflow.com/questions/286275/gray-out-image-with-css/... 获取我的答案在这个问题上
坂田Gintoki

Answers:


728

对CSS筛选器的支持已落入Webkit中。 因此,我们现在有了跨浏览器的解决方案。

img {
  filter: gray; /* IE6-9 */
  -webkit-filter: grayscale(1); /* Google Chrome, Safari 6+ & Opera 15+ */
  filter: grayscale(1); /* Microsoft Edge and Firefox 35+ */
}

/* Disable grayscale on hover */
img:hover {
  -webkit-filter: grayscale(0);
  filter: none;
}
<img src="http://lorempixel.com/400/200/">


Internet Explorer 10呢?

您可以使用灰色的polyfill 。


1
只有Chrome 18+支持@CamiloMartin CSS过滤器
Salman von Abbas

2
更新:最新的Google Chrome稳定版(19)现在支持CSS过滤器。好极了!=)
Salman von Abbas 2012年

6
Opera有什么解决方案吗?
Rustam

23
那么,IE10的解决方案是什么?
Tom Auger 2013年

2
对于后代:@TomAuger,此问答对IE10具有特定说明。
巴尼2014年

127

brillout.com的答案以及Roman Nurik的答案开始,并稍微放松了“ no SVG”的要求,您可以仅使用单个SVG文件和一些CSS使Firefox中的图像去饱和。

您的SVG文件将如下所示:

<?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>

将其另存为resources.svg,从现在开始可以将其重用于要更改为灰度的任何图像。

在CSS中,您可以使用Firefox特定的filter属性来引用过滤器:

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

如果您愿意,也可以添加MS专有的,应用于要转换为灰度的任何图像(在Firefox> 3.5,IE8中有效)

编辑这是一篇不错的博客文章,它描述了如何filter在SalmanPK的答案中使用新的CSS3 属性,并与此处描述的SVG方法配合使用。使用这种方法,您将得到如下结果:

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 */
}

进一步的浏览器支持信息在这里


6
在webkit中,您需要执行以下操作:-webkit-filter: grayscale(100%);然后执行以下操作:-webkit-filter: grayscale(0);将其删除。
SeanJA

@SeanJA感谢您的更新,WebKit 于12月
robertc 2012年

我在linux笔记本电脑和win7机器上的chrome beta版中都看到了它。在chrome稳定版中,它似乎无法在linux中工作(但再次,可能是linux的版本落后于Windows)。
SeanJA

1
这种方法在Chrome中对我来说效果很好,但在Safari中没有效果。在FF中,这会使我的图像在悬停之前不可见。
colmtuite 2012年

85

对于Firefox,您无需创建filter.svg文件,可以使用data URI scheme

拿第一个答案的css代码可以得出:

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+ */

注意用文件编码替换“ utf-8”字符串。

此方法应该比其他方法更快,因为浏览器不需要执行第二个HTTP请求。


3
仅需注意,即可避免头痛:YUI Compressor在数据URL中去除空格。因此,如果您想使用此解决方案,则可以考虑使用其他缩小器。
Malte

6
@Malte还是只用“%20”字符串替换空格?
mquandalle

灰色:@mquandalle不幸IE10不支持过滤blogs.msdn.com/b/ie/archive/2011/12/07/...
Jedi.za

1
在Firefox上,我的灰色很淡。有什么方法可以增加对比度或使其稍微变暗吗?其他浏览器看起来很棒。
square_eyes

27

更新:我将其制作成完整的GitHub存储库,包括适用于IE10和IE11的JavaScript polyfill:https : //github.com/karlhorky/gray

我最初使用SalmanPK的答案,但随后创建了以下变体,以消除SVG文件所需的额外HTTP请求。内联SVG可在Firefox 10及更高版本中使用,低于10的版本不再占全球浏览器市场的1%。

从那以后,我一直在此博客文章上更新解决方案,添加了对褪色的支持,使用SVG的IE 10/11支持以及演示中的部分灰度。

img.grayscale {
  /* Firefox 10+, Firefox on Android */
  filter: url("data:image/svg+xml;utf8,<svg xmlns='http://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>#grayscale");

  /* IE 6-9 */
  filter: gray;

  /* Chrome 19+, Safari 6+, Safari 6+ iOS */
  -webkit-filter: grayscale(100%);
}

img.grayscale.disabled {
  filter: none;
  -webkit-filter: grayscale(0%);
}


11

今天遇到了同样的问题。我最初使用SalmanPK解决方案,但发现效果在FF和其他浏览器之间有所不同。这是因为转换矩阵仅适用于亮度,而不适用于像Chrome / IE中的滤镜那样的亮度。令我惊讶的是,我发现SVG中的其他更简单的解决方案也可以在FF4 +中使用并产生更好的结果:

<svg xmlns="http://www.w3.org/2000/svg">
  <filter id="desaturate">
    <feColorMatrix type="saturate" values="0"/>
  </filter>
</svg>

使用CSS:

img {
    filter: url(filters.svg#desaturate); /* Firefox 3.5+ */
    filter: gray; /* IE6-9 */
    -webkit-filter: grayscale(1); /* Google Chrome & Safari 6+ */
}

另一个警告是,IE10在符合标准的模式下不再支持“ filter:grey:”,因此需要在标头中切换兼容模式才能工作:

<meta http-equiv="X-UA-Compatible" content="IE=9" />

2
似乎是一个更好,更简单的解决方案-如果SalmanPK和mquandalle为此更新了他们的解决方案,那就更好了。显然他们使用的矩阵已损坏 <br> <br>这是嵌入式数据版本: filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'saturate\' values=\'0\'/></filter></svg>#grayscale");
psdie 2014年

11

仅使用CSS来实现灰度的最简单方法是通过filter属性。

img {
    -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
    filter: grayscale(100%);
}

该属性仍然不受完全支持,仍然需要该-webkit-filter属性在所有浏览器中提供支持。



7

对于在其他答案中询问被忽略的IE10 +支持的人们,请查看以下CSS:

img.grayscale:hover {
    filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'1 0 0 0 0, 0 1 0 0 0, 0 0 1 0 0, 0 0 0 1 0\'/></filter></svg>#grayscale");
}

svg {
    background:url(http://4.bp.blogspot.com/-IzPWLqY4gJ0/T01CPzNb1KI/AAAAAAAACgA/_8uyj68QhFE/s400/a2cf7051-5952-4b39-aca3-4481976cb242.jpg);
}

svg image:hover {
    opacity: 0;
}

应用于此标记:

<!DOCTYPE HTML>
<html>
<head>

    <title>Grayscaling in Internet Explorer 10+</title>

</head>
<body>

    <p>IE10 with inline SVG</p>
    <svg xmlns="http://www.w3.org/2000/svg" id="svgroot" viewBox="0 0 400 377" width="400" height="377">
      <defs>
         <filter id="filtersPicture">
           <feComposite result="inputTo_38" in="SourceGraphic" in2="SourceGraphic" operator="arithmetic" k1="0" k2="1" k3="0" k4="0" />
           <feColorMatrix id="filter_38" type="saturate" values="0" data-filterid="38" />
        </filter>
      </defs>
      <image filter="url(&quot;#filtersPicture&quot;)" x="0" y="0" width="400" height="377" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://4.bp.blogspot.com/-IzPWLqY4gJ0/T01CPzNb1KI/AAAAAAAACgA/_8uyj68QhFE/s1600/a2cf7051-5952-4b39-aca3-4481976cb242.jpg" />
    </svg>

</body>
</html>

有关更多演示,请查看IE testdrive的CSS3图形部分和该旧的IE博客http://blogs.msdn.com/b/ie/archive/2011/10/14/svg-filter-effects-in-ie10.aspx


7

在Internet Explorer中使用filter属性。

在webkit和Firefox中,目前无法仅通过CSS对图像进行脱字符处理。因此,您需要使用canvas或SVG作为客户端解决方案。

但是我认为使用SVG更为优雅。查阅我的博客文章,了解适用于Firefox和Webkit的SVG解决方案:http : //webdev.brillout.com/2010/10/desaturate-image-without-javascript.html

严格来说,由于SVG是HTML,所以解决方案是纯html + css :-)


嗨,brillout。我注意到您的灰度实际上在野生动物园中失败了。有跟进吗?谢谢
天鹅

1
SVG 不是 HTML。这是一个完全不同的规范。
卡米洛·马丁


1
@robertc该链接是关于将SVG放入HTML中,但这是SVG规范,这是HTML规范。两者彼此相似(或与XML相似)并不意味着它们是同一件事……
Camilo Martin

1
但是它链接到参考中的SVG规范...它没有定义SVG,只是说浏览器应该解析它。在这方面就像Javascript或CSS。
卡米洛·马丁

6

现代浏览器已经有一段时间提供了一种新的方法。

background-blend-mode可让您获得一些有趣的效果,其中之一就是灰度转换

设置在白色背景上的亮度值允许使用。(悬停以灰色显示)

.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>

从图像中获取光度,从背景中获取颜色。由于始终为白色,因此没有颜色。

但是它允许更多。

您可以为效果设置3层设置动画。第一个是图像,第二个是白黑渐变。如果对此应用乘法混合模式,则在白色部分上将获得与以前一样的白色结果,但是在黑色部分上的原始图像(乘以白色将得到白色,而乘以黑色则无效)。

在渐变的白色部分,您将获得与以前相同的效果。在渐变的黑色部分,您将图像混合在其自身上,结果是未修改的图像。

现在,所需要做的就是移动渐变以使该效果动态化:(悬停以彩色显示)

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>

参考

相容性矩阵


1
@Andy我开始回答在现代浏览器中
vals

如果不img为图像使用标签,该如何应用background: url()
Mohammad Elbanna '18

1
@MohammadElbanna您需要使用mix-blend-mode而不是background-blend-mode
vals

5
img {
    -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
    filter: grayscale(100%);
}

4

也许这样可以帮助你

img {
    -webkit-filter: grayscale(100%); /* Chrome, Safari, Opera */
    filter: grayscale(100%);
}

w3schools.org


3

如果我记得正确使用私有CSS属性,实际上使用IE会更容易。FILTER: Grayhttp://www.ssi-developer.net/css/visual-filters.shtml尝试一下

Axe的方法只是使图像透明并在其后面具有黑色背景。我敢肯定,您可以说这是灰度的。

尽管您不想使用Javascript,但我认为您必须使用它。您也可以使用服务器端语言来实现。


我什至没有Windows盒子,所以谢谢,但这对我没有多大用处。

在这种情况下,您可以使用带有IE的虚拟机来查看它,实现ax的方法或使用canvas ...请注意,使用canvas对大型图像进行灰度缩放可能会对Javascript引擎造成很大的负担。
alex

7
filter: gray版本4开始,Internet Explorer中就存在该功能。他们为他们的产品取了很多废话-是的!-但是他们在这些方面确实领先于时代
Pekka 2010年


2

从当前版本19.0.1084.46添加了对Webkit中本机CSS筛选器的支持

因此-webkit-filter:grayscale(1)将起作用,并且比SVG的webkit方法更容易...


2

这是LESS的mixin,可让您选择任何不透明度。自己为普通CSS以不同百分比填写变量。

这里的整洁提示,它对矩阵使用了饱和类型,因此您无需做任何花哨的操作即可更改百分比。

.saturate(@value:0) {
    @percent: percentage(@value);

    filter: url("data:image/svg+xml;utf8,<svg%20xmlns='http://www.w3.org/2000/svg'><filter%20id='grayscale'><feColorMatrix%20type='saturate'%20values='@value'/></filter></svg>#grayscale"); /* Firefox 3.5+ */
    filter: grayscale(@percent); /* Current draft standard */
    -webkit-filter: grayscale(@percent); /* New WebKit */
    -moz-filter: grayscale(@percent);
    -ms-filter: grayscale(@percent);
    -o-filter: grayscale(@percent);
}

然后使用它:

img.desaturate {
    transition: all 0.2s linear;
    .saturate(0);
    &:hover {
        .saturate(1);
    }
}

2

您不需要使用太多的前缀即可充分使用,因为如果您为旧的Firefox选择前缀,则不需要为新的Firefox使用前缀。

因此,要充分使用,请使用以下代码:

img.grayscale {
    filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://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>#grayscale"); /* Firefox 10+, Firefox on Android */
    filter: gray; /* IE6-9 */
    -webkit-filter: grayscale(100%); /* Chrome 19+, Safari 6+, Safari 6+ iOS */
}

img.grayscale.disabled {
    filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'1 0 0 0 0, 0 1 0 0 0, 0 0 1 0 0, 0 0 0 1 0\'/></filter></svg>#grayscale");
    filter: none;
    -webkit-filter: grayscale(0%);
}

2

作为对他人答案的补充,有可能在FF上将图像去饱和一半而不会引起SVG 矩阵的麻烦:

<feColorMatrix type="saturate" values="$v" />

在和$v之间。相当于01filter:grayscale(50%);

现场示例:

有关MDN的参考


1

基于robertc的答案

为了获得从彩色图像到灰度图像的正确转换,而不是使用像这样的矩阵:

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

您应该使用如下转换矩阵:

0.299 0.299 0.299 0
0.587 0.587 0.587 0
0.112 0.112 0.112 0
0     0     0     1

这对于所有基于RGBA(红-绿-蓝-alpha)模型的图像类型都适用。

有关更多信息,为什么您应该使用矩阵,我在以下链接中发布了robertc的一张支票的可能性更高:


我同意0.3333是错误的;0.2126 0.7152 0.0722 0 0似乎相当于<fecolormatrix type="saturate" values="0">
Neil

可以在以下Internet档案库中找到“此处可以找到一些C#和VB代码”的链接:web.archive.org/web/20110220101001/http
//www.bobpowell.net/…– thisgeek

与“亮度和色差信号”的链接也被断开。我找不到替代品。
thisgeek

0

一种糟糕但可行的解决方案:使用Flash对象渲染图像,然后为您提供Flash中所有可能的转换。

如果您的用户使用的是最新的浏览器,并且 Firefox 3.5和Safari 4支持它(我不知道是否支持),则可以调整图像的CSS 颜色配置文件属性,将其设置为灰度ICC个人资料网址。但是,如果不是,那就很多!


0

对老年人浏览器的另一种可能是通过伪元素或内嵌标记产生的使用掩模。

将绝对位置悬停在img上(或不需要单击或选择的文本区域)可以通过rgba()或translucide png紧密模拟色标效果。

它不会给出一个单一的色标,但是会遮盖颜色超出范围的颜色。

通过伪元素在10种不同颜色的代码笔上进行测试,最后是灰色。http://codepen.io/gcyrillus/pen/nqpDd(重新加载以切换到其他图像)



0

试试这个jQuery插件。虽然,这不是纯HTML和CSS解决方案,但它是实现所需功能的一种惰性方法。您可以自定义灰度以最适合您的用法。如下使用它:

$("#myImageID").tancolor();

有一个交互式演示。您可以尝试一下。

查看有关用法的文档,这很简单。docs


0

对于Firefox中的灰度百分比,请改用饱和过滤器:(搜索“饱和”)

filter: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='saturate'><feColorMatrix in='SourceGraphic' type='saturate' values='0.2' /></filter></svg>#saturate"

-1

如果您或将来遇到类似问题的其他人可以使用PHP。(我知道您说过HTML / CSS,但也许您已经在后端使用PHP了)这是一个PHP解决方案:

我是从PHP GD库获得的,并添加了一些变量来自动执行该过程...

<?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);

?>

4
@Tom基于对原始问题的投票和偏爱,不是唯一想知道这是否可能的人。当然,这个答案可能会违反规则,但我认为降低对许多人可能有用的答案的意义不大。
Michael Martin-Smucker,2010年

1
@Tom,尽管虽然可能无法完全回答问题,但它可能派上用场,因为它实际上“解决”了灰度问题,而没有javascript的“麻烦”,也许他甚至没有考虑或不了解PHP GD,无害。@ mlms13就是重点,谢谢:)
Trufa

那是我对其他用户可以从我的脑海中溜走的帖子中受益的不好的“想法” 。
震撼

3
那确实帮助了我,使我在其他一些死胡同之后走上了正确的轨道。我发现使用“ imagefilter($ source,IMG_FILTER_GRAYSCALE);” 虽然给出了更好的结果。(仅限PHP 5)
chrismacp 2010年

5
投票结束,因为这实际上是不合时宜的。在服务器端对图像进行灰度缩放与CSS / HTML完全不同。
西蒙·斯坦伯格
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.