我有一个图标,我想用CSS改变颜色。它是在CSS中内联的数据优化的SVG中。
通常情况下,此不可能。这就是图标字体被发明的原因;它们相对于SVG的主要优势是能够从CSS中接收color
和text-shadow
规则。好吧,CSS filters现在能够同时处理任意图像,they now work in all Blink, Webkit and Gecko browsers和can be expected for future IE/Spartan。
text-shadow
更换很容易;只需使用drop-shadow
filter。
尽管所有必要的滤镜都在这里,但是,将图像着色为特定的颜色已被证明非常棘手。到目前为止,我的理论如下:
contrast(0)
将整个图像变为纯灰色,同时保持Alpha通道(Mozilla维基称它变黑了,但在所有浏览器中它变为灰色,必须是拼写错误)。sepia(1)
,因为我们无法对灰色图像上的色调/饱和度进行操作。这样可以确保整个图像由我们可以进行数学运算的参考颜色组成;具体而言,#AC9977
。此时,我们应该能够使用hue-rotate
,saturate
和brightness
将整个图像从现在的实体#AC9977
转换为我们想要的任何颜色。
首先,浏览器使用什么颜色坐标?我无法理解the spec是否确定它是否正在使用HSL (Lightness) or HSV (Value),但由于HSB( Brightness )是HSV的另一个名称,我想它正在使用HSV。此外,使用像brightness(999)
这样的东西会使颜色饱和(而不是使它们变成白色),这会在HSV中发生,而不会在HSL中发生。
基于这个假设,我们将按如下方式进行:
#AC9977
与我们想要的颜色之间的色调差异,并使用hue-rotate
。saturate
。brightness
。由于这不是手工完成的事情,我们将使用LESS preprocessor:
.colorize(@color) {
@sepiaGrey: #AC9977;
@hOffset: (hsvhue(@color) - hsvhue(@sepiaGrey)) * 1deg;
@sRatio: unit(hsvsaturation(@color) / hsvsaturation(@sepiaGrey));
@vRatio: unit(hsvvalue(@color) / hsvvalue(@sepiaGrey));
-webkit-filter: contrast(0) sepia(1) hue-rotate(@hOffset) saturate(@sRatio) brightness(@vRatio);
filter: contrast(0) sepia(1) hue-rotate(@hOffset) saturate(@sRatio) brightness(@vRatio);
}
根据我的理解,这应该有效。 But it isn't。 为什么以及如何使其发挥作用?
将图标视为图像或元素(背景图像,基于CSS的形状等),使用任何颜色,并使用透明度定义的形状(不可以简单重叠的矩形图像。我想让它完全由CSS的特定颜色组成(大概是使用filters
)。
我计划将其实现为带有颜色参数的LESS mixin,但只需指导HSB函数背后的逻辑即可。
答案 0 :(得分:3)
我有时试图达到你想要的目标,并且没有成功。
无论如何,您还可以使用混合模式:
div {
background-color: green;
mix-blend-mode: color;
position: absolute;
width: 200px;
height: 400px;
}

<div></div>
<img src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Hsl-hsv_models.svg/400px-Hsl-hsv_models.svg.png" height="400">
&#13;
我想念透明度要求。让我们再试一次:-)。缺点:您需要将图像设置2次。
#test1 {
background: linear-gradient(red, red), url("http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png");
width: 100%;
height: 500px;
background-blend-mode: hue;
-webkit-mask-image: url("http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png");
}
body {
background-color: lightblue;
}
&#13;
<div id="test1">
</div>
&#13;
确定;让我们说想要的结果是:你有一个图像,它将充当面具。您希望使用此蒙版在现有图像上设置彩色叠加,但您希望在CSS样式中指定颜色,以便可以轻松编辑。
如果您可以更改图像,那么要使用的通道是亮度而不是alpha,以下示例可以是您的解决方案 你需要一个灰色和黑色的滤镜,比如这个
.test {
width: 200px;
height: 200px;
display: inline-block;
background-image: url(http://i.stack.imgur.com/kxKXy.png);
background-size: cover;
background-blend-mode: exclusion;
mix-blend-mode: hard-light;
}
.testred {
background-color: red;
}
.testblue {
background-color: blue;
}
body {
background: repeating-linear-gradient(45deg, lightblue 0px, lightyellow 50px);
}
&#13;
<div class="test testred"></div>
<div class="test testblue"></div>
&#13;
答案 1 :(得分:1)
您必须创建一个通过CSS过滤器引用的SVG过滤器才能接近这一点。它不是真正的叠加混合 - 需要混合模式。但我认为它实际上可以让你得到你想要的东西。请注意,滤镜中的色调旋转基本上是破坏的 - 它只是RGB空间中的近似值,它会使饱和的颜色非常错误。 (它实际上是使用原始的SVG过滤器数学)。
<svg width="800px" height="600px">
<defs>
<filter id="fakeOverlay">
<feColorMatrix type="luminanceToAlpha" result="L2A"/>
<feFlood flood-color="cyan" result="colorfield"/>
<feBlend mode="multiply" in="L2A" in2="colorfield"/>
<feComposite operator="in" in2="SourceGraphic"/>
</filter>
</defs>
<image filter="url(#fakeOverlay)" width="800" height="400" xlink:href="http://i.stack.imgur.com/Mboab.png"/>
</svg>
答案 2 :(得分:0)
查看有关CSS Masks的这篇文章:http://thenittygritty.co/css-masking
答案 3 :(得分:0)
我在数学方面取得了一些进展,但它们并不漂亮;理想情况下,我相信在以下CSS过滤器中最多可以表示任何颜色:
(-webkit-)filter: contrast(0) sepia(1) hue-rotate(X) saturate(Y) brightness(Z);
换句话说,理想情况下,我们应该能够将任何颜色表示为相对于棕褐色灰色(#AC9977
)的色调,饱和度和亮度坐标。
虽然我仍然没有办法做到这一点(也不确定是否可能),但我设法制作了一个接受任何纯色(R,G,B,C,M,Y)的实现或任何中性色(白色,黑色和灰色)。一些是优化的(如黑色只是brightness(0)
)。此外,如果您指定的颜色具有透明度,则该透明度将添加为opacity
过滤器。
这是迄今为止的代码(用LESS编写):
// Filter prefixer.
.filter(@filters) { -webkit-filter+_: @filters; filter+_: @filters; }
// Helper that conditionally adds opacity filter when color calls for it.
._conditional-opacity(@color) when (alpha(@color) < 1) {
.filter(round(opacity(alpha(@color)), 3));
}
// Helper that adds a brightness filter when necessary.
._conditional-brightness(@channel) when (@channel < 255) {
.filter(brightness(round(@channel / 255, 3)));
}
// Special case for pure black.
.colorize(@color) when (fade(@color, 100%) = #000) {
.filter(brightness(0));
._conditional-opacity(@color);
}
// Special case for pure grey and off-by-one-grey.
.colorize(@color) when (fade(@color, 100%) = #7F7F7F),
(fade(@color, 100%) = #808080) {
.filter(contrast(0));
._conditional-opacity(@color);
}
// Special case for shades of pure red.
.colorize(@color) when (red(@color) > 0)
and (green(@color) = 0)
and (blue(@color) = 0) {
.filter(contrast(0) sepia(1) saturate(999));
._conditional-brightness(red(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure green.
.colorize(@color) when (red(@color) = 0)
and (green(@color) > 0)
and (blue(@color) = 0) {
.filter(contrast(0) sepia(1) hue-rotate(99deg) saturate(999));
._conditional-brightness(green(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure blue.
.colorize(@color) when (red(@color) = 0)
and (green(@color) = 0)
and (blue(@color) > 0) {
.filter(contrast(0) sepia(1) hue-rotate(199deg) saturate(999));
._conditional-brightness(blue(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure cyan.
.colorize(@color) when (red(@color) = 0)
and (green(@color) > 0)
and (blue(@color) = green(@color)) {
.filter(contrast(0) sepia(1) invert(1) saturate(999));
._conditional-brightness(blue(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure magenta.
.colorize(@color) when (red(@color) = blue(@color))
and (green(@color) = 0)
and (blue(@color) > 0) {
.filter(contrast(0) sepia(1) hue-rotate(-99deg) saturate(999));
._conditional-brightness(red(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure yellow.
.colorize(@color) when (red(@color) > 0)
and (green(@color) = red(@color))
and (blue(@color) = 0) {
.filter(contrast(0) sepia(1) hue-rotate(199deg) saturate(999) invert(1));
._conditional-brightness(green(@color));
._conditional-opacity(@color);
}
// Special case for shades of pure grey and white.
.colorize(@color) when (red(@color) = green(@color))
and (green(@color) = blue(@color))
and not (blue(@color) = 0) // We've optimized these before.
and not (blue(@color) = 127)
and not (blue(@color) = 128) {
.filter(contrast(0) brightness(round(blue(@color) / 255 * 2 + .00765, 3)));
._conditional-opacity(@color);
}
.colorize(@color) when (default()) {
// General case not figured out yet.
}
如果你想玩它,here's a codepen(它自动编译LESS)。
请注意,这还不够好,如果您发布更好的答案(包括使用不同的方法来解决问题),我可能会接受您的,并且不接受我自己的答案,除非它可以代表任何给定的颜色(目前它不能;我现在可能已经放弃了它。)