将 SVG 输出直接嵌入到页面代码中,我可以简单地使用 CSS 修改填充颜色,如下所示:
polygon.mystar {
fill: blue;
}
circle.mycircle {
fill: green;
}
这很好用,但是我正在寻找一种方法来修改作为背景图像的 SVG 的“填充”属性。
html {
background-image: url(../img/bg.svg);
}
我现在如何更改颜色?甚至可能吗?
作为参考,这里是我的外部 SVG 文件的内容:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve">
<polygon class="mystar" fill="#3CB54A" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679
118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/>
<circle class="mycircle" fill="#ED1F24" cx="202.028" cy="58.342" r="12.26"/>
</svg>
您可以使用 CSS 掩码,使用“掩码”属性,您可以创建一个应用于元素的掩码。
.icon {
background-color: red;
-webkit-mask-image: url(icon.svg);
mask-image: url(icon.svg);
}
有关更多信息,请参阅这篇精彩的文章:https://codepen.io/noahblon/post/coloring-svgs-in-css-background-images
我需要类似的东西,并想坚持使用 CSS。这里有 LESS 和 SCSS mixin 以及可以帮助你的纯 CSS。不幸的是,它的浏览器支持有点松懈。有关浏览器支持的详细信息,请参见下文。
少混合:
.element-color(@color) {
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="@{color}" ... /></g></svg>');
}
更少的用法:
.element-color(#fff);
SCSS 混合:
@mixin element-color($color) {
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="#{$color}" ... /></g></svg>');
}
SCSS 用法:
@include element-color(#fff);
CSS:
// color: red
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="red" ... /></g></svg>');
Here is more info 将完整的 SVG 代码嵌入到您的 CSS 文件中。它还提到了浏览器兼容性,这对于这是一个可行的选择来说有点太小了。
#
字符进行 urlencode 才能使其在 Firefox 中工作。所以像 <svg fill="#ffffff" ...></svg>
这样的东西变成了 <svg fill="%23ffffff" ...></svg>
。
一种方法是从某种服务器端机制为您的 svg 提供服务。只需创建一个根据 GET 参数输出 svg 的资源服务器端,然后在某个 url 上提供它。
然后你只需在你的css中使用那个url。
因为作为背景 img,它不是 DOM 的一部分,您无法对其进行操作。另一种可能性是定期使用它,以正常方式将其嵌入页面中,但绝对定位,使其全宽和页面高度,然后使用 z-index css 属性将其放在所有其他 DOM 元素后面在一个页面上。
<?php header('Content-type: image/svg+xml'); ?>
filter
或 mask-image
设置样式。
还有一种方法是使用掩码。然后更改被屏蔽元素的背景颜色。这与更改 svg 的填充属性具有相同的效果。
HTML:
<glyph class="star"/>
<glyph class="heart" />
<glyph class="heart" style="background-color: green"/>
<glyph class="heart" style="background-color: blue"/>
CSS:
glyph {
display: inline-block;
width: 24px;
height: 24px;
}
glyph.star {
-webkit-mask: url(star.svg) no-repeat 100% 100%;
mask: url(star.svg) no-repeat 100% 100%;
-webkit-mask-size: cover;
mask-size: cover;
background-color: yellow;
}
glyph.heart {
-webkit-mask: url(heart.svg) no-repeat 100% 100%;
mask: url(heart.svg) no-repeat 100% 100%;
-webkit-mask-size: cover;
mask-size: cover;
background-color: red;
}
您可以在此处找到完整的教程:http://codepen.io/noahblon/blog/coloring-svgs-in-css-background-images(不是我自己的)。它提出了多种方法(不限于掩码)。
mask
:caniuse.com/#search=mask
mask-image
的 Edge added support。
使用棕褐色滤镜以及色调旋转、亮度和饱和度来创建我们想要的任何颜色。
.colorize-pink {
filter: brightness(0.5) sepia(1) hue-rotate(-70deg) saturate(5);
}
https://css-tricks.com/solved-with-css-colorizing-svg-backgrounds/
使用 Sass 是可能的!您唯一需要做的就是对您的 svg 代码进行 url 编码。这可以通过 Sass 中的辅助函数来实现。我为此做了一个codepen。看这个:
http://codepen.io/philippkuehn/pen/zGEjxB
// choose a color
$icon-color: #F84830;
// functions to urlencode the svg string
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
@function url-encode($string) {
$map: (
"%": "%25",
"<": "%3C",
">": "%3E",
" ": "%20",
"!": "%21",
"*": "%2A",
"'": "%27",
'"': "%22",
"(": "%28",
")": "%29",
";": "%3B",
":": "%3A",
"@": "%40",
"&": "%26",
"=": "%3D",
"+": "%2B",
"$": "%24",
",": "%2C",
"/": "%2F",
"?": "%3F",
"#": "%23",
"[": "%5B",
"]": "%5D"
);
$new: $string;
@each $search, $replace in $map {
$new: str-replace($new, $search, $replace);
}
@return $new;
}
@function inline-svg($string) {
@return url('data:image/svg+xml;utf8,#{url-encode($string)}');
}
// icon styles
// note the fill="' + $icon-color + '"
.icon {
display: inline-block;
width: 50px;
height: 50px;
background: inline-svg('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">
<path fill="' + $icon-color + '" d="M18.7,10.1c-0.6,0.7-1,1.6-0.9,2.6c0,0.7-0.6,0.8-0.9,0.3c-1.1-2.1-0.4-5.1,0.7-7.2c0.2-0.4,0-0.8-0.5-0.7
c-5.8,0.8-9,6.4-6.4,12c0.1,0.3-0.2,0.6-0.5,0.5c-0.6-0.3-1.1-0.7-1.6-1.3c-0.2-0.3-0.4-0.5-0.6-0.8c-0.2-0.4-0.7-0.3-0.8,0.3
c-0.5,2.5,0.3,5.3,2.1,7.1c4.4,4.5,13.9,1.7,13.4-5.1c-0.2-2.9-3.2-4.2-3.3-7.1C19.6,10,19.1,9.6,18.7,10.1z"/>
</svg>');
}
.icon {
width: 48px;
height: 48px;
display: inline-block;
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/18515/heart.svg) no-repeat 50% 50%;
background-size: cover;
}
.icon-orange {
-webkit-filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4);
filter: hue-rotate(40deg) saturate(0.5) brightness(390%) saturate(4);
}
.icon-yellow {
-webkit-filter: hue-rotate(70deg) saturate(100);
filter: hue-rotate(70deg) saturate(100);
}
现在您可以像这样在客户端实现这一点:
var green = '3CB54A';
var red = 'ED1F24';
var svg = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="320px" height="100px" viewBox="0 0 320 100" enable-background="new 0 0 320 100" xml:space="preserve"> <polygon class="mystar" fill="#'+green+'" points="134.973,14.204 143.295,31.066 161.903,33.77 148.438,46.896 151.617,65.43 134.973,56.679 118.329,65.43 121.507,46.896 108.042,33.77 126.65,31.066 "/><circle class="mycircle" fill="#'+red+'" cx="202.028" cy="58.342" r="12.26"/></svg>';
var encoded = window.btoa(svg);
document.body.style.background = "url(data:image/svg+xml;base64,"+encoded+")";
如果您尝试使用像这样的 url()
直接在 CSS 上使用和 SVG;
a:before {
content: url('data:image/svg+xml; utf8, <svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 451 451"><path d="M345.441,2...
您应该将 #
编码为 %23
,否则它将不起作用。
<svg fill="%23FFF" ...
您可以将 SVG 存储在变量中。然后根据您的需要操作 SVG 字符串(即设置宽度、高度、颜色等)。然后使用结果设置背景,例如
$circle-icon-svg: '<svg xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="10" /></svg>';
$icon-color: #f00;
$icon-color-hover: #00f;
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
@function svg-fill ($svg, $color) {
@return str-replace($svg, '<svg', '<svg fill="#{$color}"');
}
@function svg-size ($svg, $width, $height) {
$svg: str-replace($svg, '<svg', '<svg width="#{$width}"');
$svg: str-replace($svg, '<svg', '<svg height="#{$height}"');
@return $svg;
}
.icon {
$icon-svg: svg-size($circle-icon-svg, 20, 20);
width: 20px; height: 20px; background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color)}');
&:hover {
background: url('data:image/svg+xml;utf8,#{svg-fill($icon-svg, $icon-color-hover)}');
}
}
我也做了一个演示,http://sassmeister.com/gist/4cf0265c5d0143a9e734。
此代码对 SVG 做了一些假设,例如 <svg />
元素没有现有的填充颜色,并且没有设置宽度或高度属性。由于输入在 SCSS 文档中是硬编码的,因此很容易实施这些约束。
不用担心代码重复。 gzip 压缩使差异可以忽略不计。
您可以使用亮度滤镜,任何大于 1 的值都会使元素更亮,任何小于 1 的值都会使其更暗。所以,我们可以让那些浅色的 SVG 变暗,反之亦然,例如,这会使 svg 变暗:
filter: brightness(0);
为了改变颜色而不仅仅是亮度级别,我们可以使用棕褐色滤镜和色调旋转,亮度,例如:
.colorize-blue {
filter: brightness(0.5) sepia(1) hue-rotate(140deg) saturate(6);
}
您可以为此创建自己的 SCSS 函数。将以下内容添加到您的 config.rb 文件中。
require 'sass'
require 'cgi'
module Sass::Script::Functions
def inline_svg_image(path, fill)
real_path = File.join(Compass.configuration.images_path, path.value)
svg = data(real_path)
svg.gsub! '{color}', fill.value
encoded_svg = CGI::escape(svg).gsub('+', '%20')
data_url = "url('data:image/svg+xml;charset=utf-8," + encoded_svg + "')"
Sass::Script::String.new(data_url)
end
private
def data(real_path)
if File.readable?(real_path)
File.open(real_path, "rb") {|io| io.read}
else
raise Compass::Error, "File not found or cannot be read: #{real_path}"
end
end
end
然后你可以在你的 CSS 中使用它:
.icon {
background-image: inline-svg-image('icons/icon.svg', '#555');
}
您将需要编辑 SVG 文件并将标记中的任何填充属性替换为 fill="{color}"
图标路径始终与同一 config.rb 文件中的 images_dir 参数相关。
与其他一些解决方案类似,但这非常干净,可以让您的 SCSS 文件保持整洁!
对于单色背景,您可以使用带有蒙版的 svg,其中应显示背景颜色
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" preserveAspectRatio="xMidYMid meet" focusable="false" style="pointer-events: none; display: block; width: 100%; height: 100%;" >
<defs>
<mask id="Mask">
<rect width="100%" height="100%" fill="#fff" />
<polyline stroke-width="2.5" stroke="black" stroke-linecap="square" fill="none" transform="translate(10.373882, 8.762969) rotate(-315.000000) translate(-10.373882, -8.762969) " points="7.99893906 13.9878427 12.7488243 13.9878427 12.7488243 3.53809523"></polyline>
</mask>
</defs>
<rect x="0" y="0" width="20" height="20" fill="white" mask="url(#Mask)" />
</svg>
而不是使用这个CSS
background-repeat: no-repeat;
background-position: center center;
background-size: contain;
background-image: url(your/path/to.svg);
background-color: var(--color);
在这里展示晚了,但是,如果您能够直接编辑 SVG 代码,我能够为 SVG 多边形添加填充颜色,例如,下面的 svg 呈现红色,而不是默认的黑色。我还没有在 Chrome 之外测试过:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
<polygon
fill="red"
fill-rule="evenodd" clip-rule="evenodd" points="452.5,233.85 452.5,264.55 110.15,264.2 250.05,390.3 229.3,413.35
47.5,250.7 229.3,86.7 250.05,109.75 112.5,233.5 "/>
</svg>
我为此找到的唯一方法是跨浏览器(又名防弹),是用 PHP 渲染 SVG 并传递查询字符串来设置颜色。
SVG,这里称为“arrow.php”
<?php
$fill = filter_input(INPUT_GET, 'fill');
$fill = strtolower($fill);
$fill = preg_replace("/[^a-z0-9]/", '', $fill);
if(empty($fill)) $fill = "000000";
header('Content-type: image/svg+xml');
echo '<?xml version="1.0" encoding="utf-8"?>';
?>
<svg xmlns="http://www.w3.org/2000/svg" width="7.4" height="12" viewBox="0 0 7.4 12">
<g>
<path d="M8.6,7.4,10,6l6,6-6,6L8.6,16.6,13.2,12Z" transform="translate(-8.6 -6)" fill="#<?php echo htmlspecialchars($fill); ?>" fill-rule="evenodd"/>
</g>
</svg>
然后你像这样调用图像
.cssclass{ background-image: url(arrow.php?fill=112233); }
仅适用于 PHP。请记住,每次更改颜色值时,浏览器都会加载新图像。
scss 创建函数
@function url-svg($icon) {
@return url("data:image/svg+xml;utf8,#{str-replace($icon, "#", "%23")}");
}
scss 使用
url-svg('<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.125 0H1.875C0.84082 0 0 0.84082 0 1.875V10.3125C0 11.3467 0.84082 12.1875 1.875 12.1875H4.6875V14.6484C4.6875 14.9355 5.01563 15.1025 5.24707 14.9326L8.90625 12.1875H13.125C14.1592 12.1875 15 11.3467 15 10.3125V1.875C15 0.84082 14.1592 0 13.125 0Z" fill="#8A8A8F"/></svg>')
生成的 CSS
url('data:image/svg+xml;utf8,<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.125 0H1.875C0.84082 0 0 0.84082 0 1.875V10.3125C0 11.3467 0.84082 12.1875 1.875 12.1875H4.6875V14.6484C4.6875 14.9355 5.01563 15.1025 5.24707 14.9326L8.90625 12.1875H13.125C14.1592 12.1875 15 11.3467 15 10.3125V1.875C15 0.84082 14.1592 0 13.125 0Z" fill="%238A8A8F"/></svg>')
str-replace 函数是从引导程序中使用的。
如果您想以简单的方式从白色换成黑色或类似的方式,请尝试
filter: invert(100%);
这是我最喜欢的方法,但您的浏览器支持必须非常先进。使用 mask 属性,您可以创建一个应用于元素的掩码。遮罩在任何地方都是不透明或实心的,下面的图像会透出来。在透明的地方,底层图像被遮盖或隐藏。 CSS mask-image 的语法类似于 background-image。look at the codepenmask
很多 IF,但如果您的预 base64 编码 SVG 开始:
<svg fill="#000000
然后base64编码的字符串将开始:
PHN2ZyBmaWxsPSIjMDAwMDAw
如果预编码的字符串开始:
<svg fill="#bfa76e
然后这编码为:
PHN2ZyBmaWxsPSIjYmZhNzZl
两个编码字符串的开头相同:
PHN2ZyBmaWxsPSIj
base64 编码的怪癖是每 3 个输入字符变成 4 个输出字符。 SVG 像这样开始,然后 6 个字符的十六进制填充颜色正好在编码块“边界”上开始。因此,您可以轻松地进行跨浏览器 JS 替换:
output = input.replace(/MDAwMDAw/, "YmZhNzZl");
但是上面的 tnt-rox 答案是前进的道路。
mask-image
实际上可以用于创建“背景图像”。要在不需要屏蔽时在元素 A 上使用此方法,请创建一个与元素 A 具有相同位置和尺寸的元素 B(使用您喜欢的任何方法)并将mask-image
应用于元素 B。