通过CSS改变PNG图像的颜色?

708

如果有一个显示简单图形的透明PNG图片,是否可以通过CSS改变它的颜色?可以使用某种叠加方式或其他方法来实现吗?


9
您可以设置background-color CSS属性。您可以创建一个不透明的部分,它将是固定的,以及一张图片的透明部分,这个透明部分可以通过CSS填充任何您喜欢的颜色。这符合您想要实现的吗? - jakub.g
2
@qbk,这值得回答,不仅仅是评论。而且你技术上比我快1秒。 - Unknown artist
2
您可以使用混合模式的伪元素来重新着色任何纯黑或纯白(背景保持透明)的图标。请参见我的答案:stackoverflow.com/a/39796437/1472114 - chrscblls
2
对于那些寻找实际、最新答案的人,而不涉及那些可怕的“过滤器”,这些过滤器完全不适用于此,可以参考以下链接:https://dev59.com/p2s05IYBdhLWcg3wJurp#32736304 你可以跳过其余部分:不用谢。 - gd1
30个回答

759

你可以在 -webkit-filterfilter 中使用滤镜: 滤镜在浏览器中相对较新,但根据以下 CanIUse 表格,在超过90%的浏览器中支持:https://caniuse.com/#feat=css-filters

你可以将图像变为灰度、深褐色等等(请看示例)。

因此,你现在可以通过滤镜更改 PNG 文件的颜色。

body {
    background-color:#03030a;
    min-width: 800px;
    min-height: 400px
}
img {
    width:20%;
    float:left; 
     margin:0;
}
/*Filter styles*/
.saturate { filter: saturate(3); }
.grayscale { filter: grayscale(100%); }
.contrast { filter: contrast(160%); }
.brightness { filter: brightness(0.25); }
.blur { filter: blur(3px); }
.invert { filter: invert(100%); }
.sepia { filter: sepia(100%); }
.huerotate { filter: hue-rotate(180deg); }
.rss.opacity { filter: opacity(50%); }
<!--- img src http://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/500px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg -->
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="original">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="saturate" class="saturate">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="grayscale" class="grayscale">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="contrast" class="contrast">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="brightness" class="brightness">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="blur" class="blur">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="invert" class="invert">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="sepia" class="sepia">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="huerotate" class="huerotate">
<img alt="Mona Lisa" src="https://images.pexels.com/photos/40997/mona-lisa-leonardo-da-vinci-la-gioconda-oil-painting-40997.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" title="opacity" class="rss opacity">

来源


16
简短的回答是大多数浏览器都没有通用解决方案。 - Trilarion
27
Huerotate或Saturate对白色图像会有任何影响吗? - ki9
6
2016 年更新:这现在在几乎所有浏览器中都可以使用,除了 IE:http://caniuse.com/#feat=css-filters - Stan
6
有时候你无法控制起始图像。所以,看起来你同意我的观点是正确的,你不能从黑色或白色得到任何颜色。哦,我玩了远超过5分钟才得出这个结论。 - AsGoodAsItGets
11
同时请说明您可以执行此类操作:.gifcorrect{ filter: invert(28%) sepia(100%) hue-rotate(-180deg) saturate(3); },这意味着您可以将黑色和透明或灰度图像转换为彩色,并且即使在动画GIF上也可以正常工作。 - tatsu
显示剩余15条评论

427

我发现了这个很棒的CodePen示例,你可以插入你的十六进制颜色值,它将返回应用此颜色到PNG所需的滤镜

CSS滤镜生成器,将黑色转换为目标十六进制颜色

例如,我需要我的PNG具有以下颜色#1a9790

然后,您必须将以下滤镜应用于您的PNG

filter: invert(48%) sepia(13%) saturate(3207%) hue-rotate(130deg) brightness(95%) contrast(80%);

PS:本CodePen基于MultiplyByZer0在此处给出的精彩答案:如何仅使用CSS滤镜将黑色转换为任何给定颜色

所有功劳归于他👏


3
我用这段代码将颜色从蓝色变成了白色:filter: invert(1%) sepia(1%) saturate(1%) hue-rotate(1deg) brightness(1000%) contrast(80%); - Anjan Biswas
31
作者值得一座雕像!(注意:brightness(0) saturate(100%)是可选的,它消除了任何疑虑。) - Jackie Degl'Innocenti
3
如果有人需要,这里是该代码的 TS 转换版本 https://gist.github.com/dwjohnston/7e60bf5d4b6c071cd869f9f346241c08 - dwjohnston
2
这适用于黑色背景或图像。对于白色元素,请尝试调整反转参数以获得正确的颜色。 - ojathelonius
2
这个 CodePen 基于 MultiplyByZer0 在这里提供的精彩答案:https://dev59.com/5FgQ5IYBdhLWcg3wUSO3#43960991 - zehawk
显示剩余4条评论

61

编辑 2023年7月:当我写下这个答案时,已经超过10年了,CSS滤镜还不是一件事情,但现在很容易在PNG图像上添加阴影并赋予其所需的颜色。请查看我的新答案:https://dev59.com/p2s05IYBdhLWcg3wJurp#76648616


你可能想要查看图标字体。http://css-tricks.com/examples/IconFont/ 编辑:我正在我的最新项目中使用Font-Awesome。你甚至可以使用它进行引导。只需将下面的代码放在你的标签中:
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css" rel="stylesheet">

<!-- And if you want to support IE7, add this aswell -->
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome-ie7.min.css" rel="stylesheet">

然后继续添加一些像这样的图标链接:
<a class="icon-thumbs-up"></a>

这是完整的备忘单
--编辑--
Font-Awesome在新版本中使用了不同的类名,可能是因为这样可以大幅减小CSS文件的大小,并避免出现歧义的CSS类。 所以现在你应该使用:
<a class="fa fa-thumbs-up"></a>

编辑2:

刚刚发现GitHub也使用了自己的图标字体:Octicons 可以免费下载。他们还提供了一些关于如何创建你自己的图标字体的技巧。

编辑3:

看起来Octicons仍然存在。不过它不再作为图标字体提供,而是作为一系列SVG图像。现在SVG是主流,但如果你仍然想给PNG图像上色,我想出了这个技巧:https://dev59.com/p2s05IYBdhLWcg3wJurp#76648616


1
+1 鼓励创新思维。现在有很多易于使用的在线应用程序,可以帮助您从(SVG)图像创建Web字体。 - yvan vander sanden
如果<a class="icon-thumbs-up"></a>是旧的类名,而<a class="fa fa-thumbs-up"></a>是新的类名,我认为这并不会使CSS更小,我可以看到fa和fa-thumbs-up之间有一个额外的空格,如果我没有错的话,至少要在CSS文件中添加1个额外的字节。 - brandito
Font Awesome曾经非常出色,但不幸的是它会阻塞渲染,这让Google和用户都感到不满。我们首先通过从CSS和二进制字体文件中删除未使用的字体来解决这个问题,将数据减少了约一半。现在我们正在进行彻底的删除,并用简单的精灵图替换,这不会阻塞渲染(DOM和CSSOM处理更快,使页面上的元素更快地出现),并且将数据再次减少75%,降至6KB。FA大约为100KB。CSS遮罩可能有助于我们的情况,但可能是不必要的。 - Y.K.

59

对我起作用的最简单的一行代码:

filter: opacity(0.5) drop-shadow(0 0 0 blue);

您可以将不透明度从0调整到1,以使颜色变浅或变深。


11
将投影效果重复2-3次以增强其强度。 - djdance
2
天才的解决方案,在CSS中看起来有点凌乱,但是有注释,就非常容易理解了。谢谢! - Richard KeMiKaL GeNeRaL Denton
1
无法获得完全准确的颜色,通常会是原始颜色和新颜色之间的某种混合。 - swisswiss
非常适合我的需求(我并不需要完全相同的色调) - Jealie
5
@swisswiss 不要重复使用阴影效果,加上一个饱和度滤镜,超过100%,这样就像“filter: opacity(0.5) drop-shadow(0 0 0 blue) saturate(1000%);”这样。这个做法可以一次完成所有的处理,解决SMAG所提出的问题。 - Nosajimiki
显示剩余4条评论

51

我可以使用SVG滤镜来实现这一点。您可以编写一个滤镜,将源图像的颜色与要更改的颜色相乘。在下面的代码片段中,flood-color 是我们想要更改图像颜色的颜色(在此示例中为红色)。feComposite告诉滤镜我们如何处理颜色。具有算术运算符的feComposite的公式是(k1*i1*i2 + k2*i1 + k3*i2 + k4),其中i1和i2分别是输入in/in2的颜色。因此,仅指定k1=1意味着它将执行i1*i2,这意味着将两个输入颜色相乘。

注意:这只适用于HTML5,因为这是使用内联SVG。但我认为您可以通过将SVG放在单独的文件中使其适用于旧的浏览器。我还没有尝试过那种方法。

Here's the snippet:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="60" height="90" style="float:left">
  <defs>
    <filter id="colorMask1">
      <feFlood flood-color="#ff0000" result="flood" />
      <feComposite in="SourceGraphic" in2="flood" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" />
    </filter>
  </defs>
  <image width="100%" height="100%" xlink:href="http://i.stack.imgur.com/OyP0g.jpg" filter="url(#colorMask1)" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="60" height="90" style="float:left">
  <defs>
    <filter id="colorMask2">
      <feFlood flood-color="#00ff00" result="flood" />
      <feComposite in="SourceGraphic" in2="flood" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" />
    </filter>
  </defs>
  <image width="100%" height="100%" xlink:href="http://i.stack.imgur.com/OyP0g.jpg" filter="url(#colorMask2)" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="60" height="90" style="float:left">
  <defs>
    <filter id="colorMask3">
      <feFlood flood-color="#0000ff" result="flood" />
      <feComposite in="SourceGraphic" in2="flood" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" />
    </filter>
  </defs>
  <image width="100%" height="100%" xlink:href="http://i.stack.imgur.com/OyP0g.jpg" filter="url(#colorMask3)" />
</svg>


11
你被这个回答给坑了。如果有人想要将图像着色超越filter: hue-rotate的能力,那么这就是正确的方法。 - MaxPRafferty
3
对于带透明度的图标,可以将 <feComposite in="SourceGraphic" in2="flood" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" /> 替换为 <feComposite in="flood" in2="SourceAlpha" operator="atop"/> (适用于白色、彩色和黑色)。 - Salix
1
@Salix,这正是我想要模拟iOS图像着色的东西 - 谢谢! - Aaron Ash
@AaronAsh 很高兴我的评论对你有帮助 :) - Salix

24

是的 :)

Surfin' Safari - 博客存档 » CSS Masks

WebKit现在支持CSS中的alpha蒙版。蒙版允许您使用可以用于剪切图像某些部分的模式来覆盖一个框的内容,最终显示中出现复杂形状的裁剪效果。
[...]
我们引入了新属性以提供Web设计师对这些掩模及其应用方式的大量控制。这些新属性类似于已经存在的background和border-image属性。

-webkit-mask (background)
-webkit-mask-attachment (background-attachment)
-webkit-mask-clip (background-clip)
-webkit-mask-origin (background-origin)
-webkit-mask-image (background-image)
-webkit-mask-repeat (background-repeat)
-webkit-mask-composite (background-composite)
-webkit-mask-box-image (border-image)

1
这部分是未来标准的一部分吗?因为我没有找到与Webkit无关的任何信息,还是只是苹果的风格?似乎W3建议在这种情况下使用SVG:http://www.w3.org/TR/SVG/masking.html - feeela
3
不幸的是,这似乎只适用于 Webkit,并且该博客通过使用合成图像而不是实际示例来作弊。这个答案有点离题。 - Charles Goodwin

22

我觉得我有一个解决方案,既满足了您5年前寻找的需求,而且比这里其他代码选项要简单。

使用任何白色的png图像(例如,透明背景上的白色图标),您可以添加一个::after选择器来重新着色。

.icon {
    background: url(img/icon.png); /* Your icon */
    position: relative; /* Allows an absolute positioned psuedo element */
}

.icon::after{
    position: absolute; /* Positions psuedo element relative to .icon */
    width: 100%; /* Same dimensions as .icon */
    height: 100%;
    content: ""; /* Allows psuedo element to show */
    background: #EC008C; /* The color you want the icon to change to */
    mix-blend-mode: multiply; /* Only apply color on top of white, use screen if icon is black */
}

请查看此Codepen示例(鼠标悬停时应用颜色交换):http://codepen.io/chrscblls/pen/bwAXZO


我将图片从imgur重新托管,因为加载时遇到了一些问题。 - chrscblls
在最新版本的Chrome中,似乎(透明)背景也被设置为颜色。在链接的示例中,当我悬停时,我只看到一个不透明的粉色正方形...在Firefox中运行良好。 - logidelic
7
链接已失效。 - Steven Lu

20

大多数浏览器中,您可以使用过滤器:

  • 对于<img>元素和其他元素的背景图像都可以使用此技术。

  • 可以在CSS中静态设置过滤器,也可以使用JavaScript动态设置。

请参见下面的演示。


<img> 元素

您可以将此技术应用于 <img> 元素:

#original, #changed {
    width: 45%;
    padding: 2.5%;
    float: left;
}

#changed {
    -webkit-filter : hue-rotate(180deg);
    filter : hue-rotate(180deg);
}
<img id="original" src="http://i.stack.imgur.com/rfar2.jpg" />

<img id="changed" src="http://i.stack.imgur.com/rfar2.jpg" />

背景图片

您可以将此技术应用于背景图片:

#original, #changed {
    background: url('http://i.stack.imgur.com/kaKzj.jpg');
    background-size: cover;
    width: 30%;
    margin: 0 10% 0 10%;
    padding-bottom: 28%;
    float: left;
}

#changed {
    -webkit-filter : hue-rotate(180deg);
    filter : hue-rotate(180deg);
}
<div id="original"></div>

<div id="changed"></div>

JavaScript

您可以使用JavaScript在运行时设置筛选器:

var element = document.getElementById("changed");
var filter = 'hue-rotate(120deg) saturate(2.4)';
element.style['-webkit-filter'] = filter;
element.style['filter'] = filter;
#original, #changed {
    margin: 0 10%;
    width: 30%;
    float: left;
    background: url('http://i.stack.imgur.com/856IQ.png');
    background-size: cover;
    padding-bottom: 25%;
}
<div id="original"></div>

<div id="changed"></div>


7
这个问题是关于给一个带有透明背景的白色图像上色。使用“hue-rotate”无法对白色生效。 - Synetech

19

与其他标签一样,img标签也有background属性。如果你有一个白色PNG图片,其中包含透明的形状(例如蒙版),那么你可以这样做:

<img src= 'stencil.png' style= 'background-color: red'>

166
我希望将白色部分染成不同的颜色,而不是透明部分。 - user429620
2
到目前为止,这是我找到的最佳解决方案。可惜它只能在您的网站上使用纯色背景颜色时才能起作用。 - Jules Colle
8
@Wesley,你需要翻转图像(使白色部分变成透明,其他部分变为白色),你可以使用自己喜欢的图像编辑器和蒙版来完成。 - Charles Goodwin
5
只有当图像放在白色背景中时,这种方法才有效。 - Alex

16

当将一张图片从黑色变为白色,或者从白色变为黑色时,色相旋转滤镜不起作用,因为黑色和白色在技术上并不是颜色。因此,必须使用反转滤镜属性来进行黑白颜色变化(从黑色到白色或者相反)。

.img1 { filter: invert(100%); }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接