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

实现这一点的一种方法是从某种服务器端机制提供svg。 只需创建一个资源服务器端,根据GET参数输出svg,并在某个url上提供它。

然后在css中使用这个url。

因为作为一个背景img,它不是DOM的一部分,你不能操作它。 另一种可能是定期使用它,以正常的方式将它嵌入到页面中,但绝对定位它,使它成为一个页面的全宽和高,然后使用z-index css属性将它放在页面上所有其他DOM元素的后面。


以文本形式下载svg。

使用javascript修改svg文本来更改绘制/描边/填充颜色[s]。

然后将修改后的svg字符串内联嵌入到您的css中。


现在你可以像这样在客户端实现这一点:

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+")";

小提琴!


我需要一些类似的东西,并想坚持使用CSS。这里有LESS和SCSS mixins以及普通的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>');

这里有更多关于将完整的SVG代码嵌入到CSS文件中的信息。它还提到浏览器兼容性有点太小,这是一个可行的选择。


但是,如果您能够直接编辑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>

对萨斯来说,这是可能的! 您惟一要做的就是对svg代码进行url编码。这可以通过Sass中的辅助函数实现。我做了一个代码依赖。看看这个:

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>');
}

您可以为此创建自己的SCSS函数。将以下内容添加到配置中。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}"

图标路径总是相对于相同配置中的images_dir参数。rb文件。

类似于其他一些解决方案,但这是非常干净的,并保持您的SCSS文件整洁!


还有一种方法是使用蒙版。然后更改蒙面元素的背景颜色。这与更改svg的fill属性具有相同的效果。

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(不是我自己的)。它提出了多种方法(不限于掩码)。


您可以将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压缩使得这种差异可以忽略不计。


很多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火箭的答案是前进的方向。


在某些(非常特定的)情况下,这可以通过使用过滤器来实现。例如,您可以通过使用过滤器将色调旋转45度将蓝色SVG图像更改为紫色:hue-rotate(45deg);。浏览器支持很少,但它仍然是一项有趣的技术。

Demo


这是我最喜欢的方法,但是您的浏览器支持必须非常先进。使用mask属性可以创建应用于元素的掩码。任何地方的掩模是不透明的,或固体,底层的图像显示通过。在它是透明的地方,底层图像被掩盖或隐藏。CSS mask-image的语法类似于background-image。看看这个相互依赖的掩码


 .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);
}

代码本文章和演示


你可以使用CSS掩码,使用'mask'属性,你可以创建一个应用于元素的掩码。

.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


对于单色背景,您可以使用带有掩码的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);

使用暗色滤镜以及色调旋转、亮度和饱和度来创建任何我们想要的颜色。

.colorize-pink {
  filter: brightness(0.5) sepia(1) hue-rotate(-70deg) saturate(5);
}

https://css-tricks.com/solved-with-css-colorizing-svg-backgrounds/


您可以使用亮度过滤器,任何大于1的值使元素更亮,任何小于1的值使元素更暗。因此,我们可以将这些浅色SVG设为深色,反之亦然,例如,这将使SVG变暗:

filter: brightness(0);

为了改变颜色和亮度级别,我们可以使用暗色滤镜和色调旋转,亮度,例如:

.colorize-blue {
  filter: brightness(0.5) sepia(1) hue-rotate(140deg) saturate(6);
}

如果你试图使用和SVG直接在CSS与url()像这样;

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与PHP和传递查询字符串来设置颜色。

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函数从bootstrap开始使用。


如果你想用简单的方式从白色切换到黑色或类似的,试试这个:

filter: invert(100%);

与这里链接的封闭式问题有关,但与这个问题没有直接关系。

如果有人需要替换src就像链接的问题一样,这里已经有答案了。此外,如果有人来自Vue, src路径是改变编译,我提出了一个不同的解决方案。

在我的例子中,父元素是一个链接,但实际上它可以是任何东西。

<a
  v-for="document in documents" :key="document.uuid"
  :href="document.url"
  target="_blank"
  class="item flex align-items-center gap-2 hover-parent"
>
  <img alt="documents" class="icon" src="../assets/PDF.svg" />
  <strong>{{ document.name }}</strong>
  <img class="itemImage ml-auto hide-on-parent-hover" src="../assets/download-circular-button.svg" />
  <img class="itemImage ml-auto show-on-parent-hover" src="../assets/download-circular-button-hover.svg" />
</a>
.hover-parent       .show-on-parent-hover { display: none }
.hover-parent       .hide-on-parent-hover { display: block }
.hover-parent:hover .show-on-parent-hover { display: block }
.hover-parent:hover .hide-on-parent-hover { display: none }

因此,这里的解决方案不是更改src属性,而是将两个<img>元素放在DOM中,并且只显示需要的那个元素。

如果你没有一个应该悬浮在上面的父元素,你可以简单地把两个图像都包装在一个div中。

<div class="hover-parent" >
  <img class="hide-on-parent-hover" src="../assets/download-circular-button.svg" />
  <img class="show-on-parent-hover" src="../assets/download-circular-button-hover.svg" />
</div>

你也可以将CSS更改为以下格式,因此.hover-parent父级必须是直接父级:

.hover-parent       > .show-on-parent-hover { display: none }
.hover-parent       > .hide-on-parent-hover { display: block }
.hover-parent:hover > .show-on-parent-hover { display: block }
.hover-parent:hover > .hide-on-parent-hover { display: none }

下面是另一种解决方案,使用渐变和单色图标作为背景和背景混合模式来着色图标。 它要求背景色是白色的,否则整个背景都会上色。我只在Chrome上进行了测试。

.colored-background { background-image: linear-gradient(45deg, green, green), url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23000000%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E'); background-color: #fff; background-blend-mode: lighten, normal; background-repeat: no-repeat; background-position: center, center right .8em; background-size: auto, 0.6em; color: red; display: inline-flex; align-items: center; padding: 0.5em; padding-right: 2em; height: 1.6em; width: auto; border: 1px solid gray; } .bg { background-color: #ddd; padding: 1em; } <div class="bg"> <div class="colored-background">green icon from black svg</div> </div>


由于这是谷歌上的问题,尽管年龄很大,我想我不妨在看了这里的选项后,给出一个我在遥远的2022年使用的解决方案。

这实际上只是之前的遮罩解决方案,但在一个伪元素上。

.icon {
    height: 1.5rem;
    width: 1.5rem;
}
.icon::before {
    content: "";
    display: block;
    width: 100%;
    height: 100%;
    mask-repeat: no-repeat;
    mask-position: center;
    mask-size: contain;
    mask-image: url("path/to/svg/icon.svg");
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: center;
    -webkit-mask-size: contain;
    -webkit-mask-image: url("path/to/svg/icon.svg");
}

这在今天的所有主流浏览器中都有效,尽管显然您不能使用它来拥有具有多种颜色的SVG。如果站点不允许你内联插入它们,或者你不喜欢字体图标等等,这就是商业成本。