Html 用作背景图像时修改 SVG 填充颜色

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13367868/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 03:52:11  来源:igfitidea点击:

Modify SVG fill color when being served as Background-Image

htmlcsssvg

提问by Joe

Placing the SVG output directly inline with the page code I am able to simply modify fill colors with CSS like so:

将 SVG 输出直接与页面代码内联,我可以简单地使用 CSS 修改填充颜色,如下所示:

polygon.mystar {
    fill: blue;
}?

circle.mycircle {
    fill: green;
}

This works great, however I'm looking for a way to modify the "fill" attribute of an SVG when it's being served as a BACKGROUND-IMAGE.

这很好用,但是我正在寻找一种方法来修改作为背景图像的 SVG 的“填充”属性。

html {      
    background-image: url(../img/bg.svg);
}

How can I change the colors now? Is it even possible?

我现在如何更改颜色?甚至有可能吗?

For reference, here are the contents of my external SVG file:

作为参考,以下是我的外部 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>

采纳答案by tonino.j

One way to do this is to serve your svg from some server side mechanism. Simply create a resource server side that outputs your svg according to GET parameters, and you serve it on a certain url.

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

Then you just use that url in your css.

然后你只需在你的 css 中使用那个 url。

Because as a background img, it isn't part of the DOM and you can't manipulate it. Another possibility would be to use it regularly, embed it in a page in a normal way, but position it absolutely, make it full width & height of a page and then use z-index css property to put it behind all the other DOM elements on a page.

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

回答by Ryan

I needed something similar and wanted to stick with CSS. Here are LESS and SCSS mixins as well as plain CSS that can help you with this. Unfortunately, it's browser support is a bit lax. See below for details on browser support.

我需要类似的东西,并想坚持使用 CSS。这里有 LESS 和 SCSS mixin 以及可以帮助您解决此问题的普通 CSS。不幸的是,它的浏览器支持有点松懈。有关浏览器支持的详细信息,请参见下文。

LESS mixin:

少混入:

.element-color(@color) {
  background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="@{color}" ... /></g></svg>');
}

LESS usage:

少使用:

.element-color(#fff);


SCSS mixin:

SCSS 混合:

@mixin element-color($color) {
  background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="#{$color}" ... /></g></svg>');
}

SCSS usage:

SCSS 用法:

@include element-color(#fff);


CSS:

CSS:

// color: red
background-image: url('data:image/svg+xml;utf8,<svg ...><g stroke="red" ... /></g></svg>');


Here is more infoon embedding the full SVG code into your CSS file. It also mentioned browser compatibility which is a bit too small for this to be a viable option.

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

回答by Adel

You can use CSS masks, With the 'mask' property, you create a mask that is applied to an element.

您可以使用 CSS 遮罩,通过 'mask' 属性,您可以创建一个应用于元素的遮罩。

.icon {
    background-color: red;
    -webkit-mask-image: url(icon.svg);
    mask-image: url(icon.svg);
}

For more see this great article: https://codepen.io/noahblon/post/coloring-svgs-in-css-background-images

有关更多信息,请参阅这篇很棒的文章:https: //codepen.io/noahblon/post/coloring-svgs-in-css-background-images

回答by widged

Yet another approach is to use mask. You then change the background color of the masked element. This has the same effect as changing the fill attribute of the svg.

另一种方法是使用掩码。然后更改被屏蔽元素的背景颜色。这与更改 svg 的填充属性具有相同的效果。

HTML:

HTML:

<glyph class="star"/>
<glyph class="heart" />
<glyph class="heart" style="background-color: green"/>
<glyph class="heart" style="background-color: blue"/>

CSS:

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

You will find a full tutorial here: http://codepen.io/noahblon/blog/coloring-svgs-in-css-background-images(not my own). It proposes a variety of approaches (not limited to mask).

您可以在这里找到完整的教程:http: //codepen.io/noahblon/blog/coloring-svgs-in-css-background-images(不是我自己的)。它提出了多种方法(不限于掩码)。

回答by Philipp Kühn

It's possible with Sass! The only thing you have to do is to url-encode your svg code. And this is possible with a helper function in Sass. I've made a codepen for this. Look at this:

用 Sass 是可能的!您唯一需要做的就是对您的 svg 代码进行 url 编码。这可以通过 Sass 中的辅助函数实现。我为此制作了一个代码笔。看这个:

http://codepen.io/philippkuehn/pen/zGEjxB

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

回答by Elbaz

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

codeben article and demo

代码本文章和演示

回答by jedierikb

Download your svg as text.

将您的 svg 下载为文本。

Modify your svg text using javascript to change the paint/stroke/fill color[s].

使用 javascript 修改您的 svg 文本以更改绘画/描边/填充颜色 [s]。

Then embed the modified svg string inline into your css as described here.

如上所述然后嵌入SVG修改字符串内嵌到你的CSS这里

回答by tnt-rox

Now you can achieve this on the client side like this:

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

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

Fiddle here!

在这里摆弄!

回答by Gajus

You can store the SVG in a variable. Then manipulate the SVG string depending on your needs (i.e., set width, height, color, etc). Then use the result to set the background, e.g.

您可以将 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)}');
  }
}

I have made a demo too, http://sassmeister.com/gist/4cf0265c5d0143a9e734.

我也做了一个演示,http://sassmeister.com/gist/4cf0265c5d0143a9e734

This code makes a few assumptions about the SVG, e.g. that <svg />element does not have an existing fill colour and that neither width or height properties are set. Since the input is hardcoded in the SCSS document, it is quite easy to enforce these constraints.

这段代码对 SVG 做了一些假设,例如该<svg />元素没有现有的填充颜色,并且既没有设置 width 也没有设置 height 属性。由于输入是在 SCSS 文档中硬编码的,因此很容易强制执行这些约束。

Do not worry about the code duplication. gzipcompression makes the difference negligible.

不要担心代码重复。gzip压缩使差异可以忽略不计。

回答by Lomax

You can create your own SCSS function for this. Adding the following to your config.rb file.

您可以为此创建自己的 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

Then you can use it in your CSS:

然后你可以在你的 CSS 中使用它:

.icon {
  background-image: inline-svg-image('icons/icon.svg', '#555');
}

You will need to edit your SVG files and replace any fill attributes in the markup with fill="{color}"

您将需要编辑 SVG 文件并将标记中的任何填充属性替换为 fill="{color}"

The icon path is always relative to your images_dir parameter in the same config.rb file.

图标路径始终相对于同一 config.rb 文件中的 images_dir 参数。

Similar to some of the other solutions, but this is pretty clean and keeps your SCSS files tidy!

与其他一些解决方案类似,但它非常干净并且可以保持您的 SCSS 文件整洁!