CSS 中的内联 SVG

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10768451/
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-30 04:00:02  来源:igfitidea点击:

Inline SVG in CSS

csssvg

提问by akaRem

Is it possible to use an inline SVG definition in CSS?

是否可以在 CSS 中使用内联 SVG 定义?

I mean something like:

我的意思是这样的:

.my-class {
  background-image: <svg>...</svg>;
}

回答by Raab

Yes, it is possible. Try this:

对的,这是可能的。尝试这个:

body { background-image: 
        url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='%23F00'/><stop offset='90%' stop-color='%23fcc'/> </linearGradient><rect fill='url(%23gradient)' x='0' y='0' width='100%' height='100%'/></svg>");
      }

(Note that the SVG content needs to be url-escaped for this to work, e.g. #gets replaced with %23.)

(请注意,SVG 内容需要进行 url-escaped 才能工作,例如#被替换为%23.)

This works in IE 9 (which supports SVG). Data-URLs work in older versions of IE too (with limitations), but they don't natively support SVG.

这适用于 IE 9(支持 SVG)。数据 URL 也适用于旧版本的 IE(有限制),但它们本身不支持 SVG。

回答by Mike Tommasi

A little late, but if any of you have been going crazy trying to use inline SVG as a background, the escaping suggestions above do not quite work. For one, it does not work in IE, and depending on the content of your SVG the technique will cause trouble in other browsers, like FF.

有点晚了,但是如果你们中的任何人都疯狂地尝试使用内联 SVG 作为背景,那么上面的转义建议并不完全有效。一方面,它在 IE 中不起作用,并且根据 SVG 的内容,该技术会在其他浏览器(如 FF)中引起麻烦。

If you base64 encode the svg (not the entire url, just the svg tag and its contents! ) it works in all browsers. Here is the same jsfiddle example in base64: http://jsfiddle.net/vPA9z/3/

如果您对 svg(不是整个 url,只是 svg 标签及其内容!)进行 base64 编码,则它适用于所有浏览器。这是 base64 中相同的 jsfiddle 示例:http: //jsfiddle.net/vPA9z/3/

The CSS now looks like this:

CSS 现在看起来像这样:

body { background-image: 
    url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PGxpbmVhckdyYWRpZW50IGlkPSdncmFkaWVudCc+PHN0b3Agb2Zmc2V0PScxMCUnIHN0b3AtY29sb3I9JyNGMDAnLz48c3RvcCBvZmZzZXQ9JzkwJScgc3RvcC1jb2xvcj0nI2ZjYycvPiA8L2xpbmVhckdyYWRpZW50PjxyZWN0IGZpbGw9J3VybCgjZ3JhZGllbnQpJyB4PScwJyB5PScwJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJy8+PC9zdmc+");

Remember to remove any URL escaping before converting to base64. In other words, the above example showed color='#fcc' converted to color='%23fcc', you should go back to #.

请记住在转换为 base64 之前删除任何 URL 转义。换句话说,上面的例子显示 color='#fcc' 转换为 color='%23fcc',你应该回到#。

The reason why base64 works better is that it eliminates all the issues with single and double quotes and url escaping

base64 效果更好的原因是它消除了单双引号和 url 转义的所有问题

If you are using JS, you can use window.btoa()to produce your base64 svg; and if it doesn't work (it might complain about invalid characters in the string), you can simply use https://www.base64encode.org/.

如果您使用的是 JS,则可以使用window.btoa()来生成您的 base64 svg;如果它不起作用(它可能会抱怨字符串中的无效字符),您可以简单地使用https://www.base64encode.org/

Example to set a div background:

设置 div 背景的示例:

var mySVG = "<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><linearGradient id='gradient'><stop offset='10%' stop-color='#F00'/><stop offset='90%' stop-color='#fcc'/> </linearGradient><rect fill='url(#gradient)' x='0' y='0' width='100%' height='100%'/></svg>";
var mySVG64 = window.btoa(mySVG);
document.getElementById('myDiv').style.backgroundImage = "url('data:image/svg+xml;base64," + mySVG64 + "')";
html, body, #myDiv {
  width: 100%;
  height: 100%;
  margin: 0;
}
<div id="myDiv"></div>

With JS you can generate SVGs on the fly, even changing its parameters.

使用 JS,您可以即时生成 SVG,甚至可以更改其参数。

One of the better articles on using SVG is here : http://dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/

关于使用 SVG 的一篇更好的文章在这里:http: //dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/

Hope this helps

希望这可以帮助

Mike

麦克风

回答by Davy Baert

For people who are still struggling, I managed to get this working on all modern browsers IE11 and up.

对于仍在苦苦挣扎的人,我设法在所有现代浏览器 IE11 及更高版本上运行。

base64 was no option for me because I wanted to use SASS to generate SVG icons based on any given color. For example: @include svg_icon(heart, #FF0000);This way I can create a certain icon in any color, and only have to embed the SVG shape once in the CSS. (with base64 you'd have to embed the SVG in every single color you want to use)

base64 不适合我,因为我想使用 SASS 根据任何给定颜色生成 SVG 图标。例如:@include svg_icon(heart, #FF0000);这样我可以创建任何颜色的某个图标,并且只需要在 CSS 中嵌入一次 SVG 形状。(使用 base64,您必须将 SVG 嵌入到您想要使用的每种颜色中)

There are three things you need be aware of:

您需要注意三件事:

  1. URL ENCODE YOUR SVGAs others have suggested, you need to URL encode your entire SVG string for it to work in IE11. In my case, I left out the color values in fields such as fill="#00FF00"and stroke="#FF0000"and replaced them with a SASS variable fill="#{$color-rgb}"so these can be replaced with the color I want. You can use any online converterto URL encode the rest of the string. You'll end up with an SVG string like this:

    %3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20494.572%20494.572%27%20width%3D%27512%27%20height%3D%27512%27%3E%0A%20%20%3Cpath%20d%3D%27M257.063%200C127.136%200%2021.808%20105.33%2021.808%20235.266c0%2041.012%2010.535%2079.541%2028.973%20113.104L3.825%20464.586c345%2012.797%2041.813%2012.797%2015.467%200%2029.872-4.721%2041.813-12.797v158.184z%27%20fill%3D%27#{$color-rgb}%27%2F%3E%3C%2Fsvg%3E

  1. URL编码您的 SVG正如其他人所建议的那样,您需要对整个 SVG 字符串进行 URL 编码才能在 IE11 中工作。在我的例子中,我省略了字段中的颜色值fill="#00FF00"stroke="#FF0000"并将它们替换为 SASS 变量,fill="#{$color-rgb}"以便可以将它们替换为我想要的颜色。您可以使用任何在线转换器对字符串的其余部分进行 URL 编码。你最终会得到一个像这样的 SVG 字符串:

    %3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20494.572%20494.572%27%207width%27%27width%27%D %27512%27%3E%0A%20%20%3Cpath%20D%3D%27M257.063%200C127.136%200%2021.808%20105.33%2021.808%20235.266c0%2041.012 2010.535%%2079.541 2028.973%%20113.104L3.825 %20464.586c345%2012.797 2041.813%%2012.797 2015.467%%200%2029.872-4.721%2041.813-12.797v158.184z%27%20fill%3D%27#{$颜色RGB}%27%2F%3E%3C%2Fsvg% 3E



  1. OMIT THE UTF8 CHARSET IN THE DATA URLWhen creating your data URL, you need to leave out the charset for it to work in IE11.

    NOTbackground-image: url( data:image/svg+xml;utf-8,%3Csvg%2....)
    BUTbackground-image: url( data:image/svg+xml,%3Csvg%2....)

  1. 省略数据 URL 中的 UTF8字符集 创建数据 URL 时,您需要省略字符集以使其在 IE11 中工作。

    不是背景图片:url(data:image/svg+xml;utf-8,%3Csvg%2....)
    但是背景图片:url(data:image/svg+xml,%3Csvg%2... .)



  1. USE RGB() INSTEAD OF HEX colorsFirefox does not like # in the SVG code. So you need to replace your color hex values with RGB ones.

    NOTfill="#FF0000"
    BUTfill="rgb(255,0,0)"

  1. 使用 RGB() 代替十六进制颜色Firefox 不喜欢 SVG 代码中的 # 。所以你需要用RGB值替换你的颜色十六进制值。

    填充="#FF0000"
    填充="rgb(255,0,0)"

In my case I use SASS to convert a given hex to a valid rgb value. As pointed out in the comments, it's best to URL encode your RGB string as well (so comma becomes %2C)

就我而言,我使用 SASS 将给定的十六进制转换为有效的 rgb 值。正如评论中指出的那样,最好也对您的 RGB 字符串进行 URL 编码(因此逗号变为 %2C)

@mixin svg_icon($id, $color) {
   $color-rgb: "rgb(" + red($color) + "%2C" + green($color) + "%2C" + blue($color) + ")";
   @if $id == heart {
      background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20494.572%20494.572%27%20width%3D%27512%27%20height%3D%27512%27%3E%0A%20%20%3Cpath%20d%3D%27M257.063%200C127.136%200%2021.808%20105.33%2021.808%20235.266c0%204%27%20fill%3D%27#{$color-rgb}%27%2F%3E%3C%2Fsvg%3E');
   }
}


I realize this might not be the best solution for very complex SVG's (inline SVG never is in that case), but for flat icons with only a couple of colors this really works great.

我意识到这可能不是非常复杂的 SVG 的最佳解决方案(在这种情况下内联 SVG 从来都不是),但对于只有几种颜色的平面图标,这确实非常有效。

I was able to leave out an entire sprite bitmap and replace it with inline SVG in my CSS, which turned out to only be around 25kb after compression. So it's a great way to limit the amount of requests your site has to do, without bloating your CSS file.

我能够省略整个精灵位图,并在我的 CSS 中用内联 SVG 替换它,结果发现压缩后只有 25kb 左右。因此,这是限制您的站点必须执行的请求数量的好方法,而且不会使您的 CSS 文件膨胀。

回答by araks

On Mac/Linux, you can easily convert a SVG file to a base64 encoded value for CSS background attribute with this simple bash command:

在 Mac/Linux 上,您可以使用以下简单的 bash 命令轻松地将 SVG 文件转换为 CSS 背景属性的 base64 编码值:

echo "background: transparent url('data:image/svg+xml;base64,"$(openssl base64 < path/to/file.svg)"') no-repeat center center;"

Tested on Mac OS X. This way you also avoid the URL escaping mess.

在 Mac OS X 上测试过。这样你也可以避免 URL 转义混乱。

Remember that base64 encoding an SVG file increase its size, see css-tricks.com blog post.

请记住,对 SVG 文件进行 base64 编码会增加其大小,请参阅css-tricks.com 博客文章

回答by Lea Rosema

I've forked a CodePen demo that had the same problem with embedding inline SVG into CSS. A solution that works with SCSS is to build a simple url-encoding function.

我已经分叉了一个 CodePen 演示,它在将内联 SVG 嵌入到 CSS 中遇到了同样的问题。一个适用于 SCSS 的解决方案是构建一个简单的 url-encoding 函数。

A string replacement function can be created from the built-in str-slice, str-index functions (see css-tricks, thanks to Hugo Giraudel).

可以从内置的 str-slice 和 str-index 函数创建字符串替换函数(请参阅css-tricks,感谢 Hugo Giraudel)。

Then, just replace %,<,>,",',with the %xxcodes:

然后,只需将%, <, >, ", ',替换为以下%xx代码:

@function svg-inline($string){
  $result: str-replace($string, "<svg", "<svg xmlns='http://www.w3.org/2000/svg'");
  $result: str-replace($result, '%', '%25');
  $result: str-replace($result, '"', '%22');
  $result: str-replace($result, "'", '%27');
  $result: str-replace($result, ' ', '%20');
  $result: str-replace($result, '<', '%3C');
  $result: str-replace($result, '>', '%3E');
  @return "data:image/svg+xml;utf8," + $result;
}

$mySVG: svg-inline("<svg>...</svg>");

html {
  height: 100vh;
  background: url($mySVG) 50% no-repeat;
}

There is also a image-inlinehelper function available in Compass, but since it is not supported in CodePen, this solution might probably be useful.

image-inlineCompass 中还有一个辅助函数可用,但由于 CodePen 不支持它,因此此解决方案可能有用。

Demo on CodePen: http://codepen.io/terabaud/details/PZdaJo/

CodePen 上的演示:http://codepen.io/terabaud/details/PZdaJo/

回答by Alex Nikulin

I found one solution for SVG. But it is work only for Webkit, I just want share my workaround with you. In my example is shown how to use SVG element from DOM as background through a filter (background-image: url('#glyph') is not working).

我找到了一种 SVG 解决方案。但它仅适用于 Webkit,我只想与您分享我的解决方法。在我的示例中,展示了如何通过过滤器将 DOM 中的 SVG 元素用作背景(背景图像:url('#glyph')不起作用)。

Features needed for this SVG icon render:

此 SVG 图标渲染所需的功能:

  1. Applying SVG filter effects to HTML elements using CSS (IE and Edge not supports)
  2. feImage fragment load supporting (firefox not supports)
  1. 使用 CSS 将 SVG 滤镜效果应用于 HTML 元素(不支持 IE 和 Edge)
  2. feImage 片段加载支持(firefox 不支持)

.test {
  /*  background-image: url('#glyph');
    background-size:100% 100%;*/
    filter: url(#image); 
    height:100px;
    width:100px;
}
.test:before {
   display:block;
   content:'';
   color:transparent;
}
.test2{
  width:100px;
  height:100px;
}
.test2:before {
   display:block;
   content:'';
   color:transparent;
   filter: url(#image); 
   height:100px;
   width:100px;
}
<svg style="height:0;width:0;" version="1.1" viewbox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
     <g id="glyph">
          <path id="heart" d="M100 34.976c0 8.434-3.635 16.019-9.423 21.274h0.048l-31.25 31.25c-3.125 3.125-6.25 6.25-9.375 6.25s-6.25-3.125-9.375-6.25l-31.202-31.25c-5.788-5.255-9.423-12.84-9.423-21.274 0-15.865 12.861-28.726 28.726-28.726 8.434 0 16.019 3.635 21.274 9.423 5.255-5.788 12.84-9.423 21.274-9.423 15.865 0 28.726 12.861 28.726 28.726z" fill="crimson"/>
     </g>
    <svg id="resized-glyph"  x="0%" y="0%" width="24" height="24" viewBox="0 0 100 100" class="icon shape-codepen">
      <use xlink:href="#glyph"></use>
    </svg>
     <filter id="image">
       <feImage xlink:href="#resized-glyph" x="0%" y="0%" width="100%" height="100%" result="res"/>
       <feComposite operator="over" in="res" in2="SourceGraphic"/>
    </filter>
 </defs>
</svg>
<div class="test">
</div>
<div class="test2">
</div>

One more solution, is use url encode

另一种解决方案是使用 url encode

var container = document.querySelector(".container");
var svg = document.querySelector("svg");
var svgText = (new XMLSerializer()).serializeToString(svg);
container.style.backgroundImage = `url(data:image/svg+xml;utf8,${encodeURIComponent(svgText)})`;
.container{
  height:50px;
  width:250px;
  display:block;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: contain;
}
<svg  height="100" width="500" xmlns="http://www.w3.org/2000/svg">
    <ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" />
</svg>
<div class="container"></div>

回答by mp31415

Inline SVG coming from 3rd party sources (like Google charts) may not contain XML namespace attribute (xmlns="http://www.w3.org/2000/svg") in SVG element (or maybe it's removed once SVG is rendered - neither browser inspector nor jQuery commands from browser console show the namespace in SVG element).

来自第 3 方来源(如 Google 图表)的内联 SVGxmlns="http://www.w3.org/2000/svg"在 SVG 元素中可能不包含 XML 命名空间属性 ( )(或者可能在渲染 SVG 后将其删除 - 浏览器检查器和来自浏览器控制台的 jQuery 命令均未显示 SVG 元素中的命名空间)。

When you need to re-purpose these svg snippets for your other needs (background-image in CSS or img element in HTML) watch out for the missing namespace. Without the namespace browsers may refuse to display SVG (regardless of the encoding utf8 or base64).

当您需要将这些 svg 片段重新用于其他需求(CSS 中的背景图像或 HTML 中的 img 元素)时,请注意缺少的命名空间。如果没有命名空间,浏览器可能会拒绝显示 SVG(无论编码 utf8 还是 base64)。