CSS中的内联SVG


283

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

我的意思是:

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

1
您想做什么,将图像“源”添加到样式表中?
Zuul 2012年

1
请注意,<img>如果SVG是多个图像的混合(除非嵌入),建议的解决方案将不适用于CSS图像,HTML 标签和其他情况,请参阅带有外部图像的蒙版的背景图像SVG不能正常工作,特别是将SVG用作限制图片
Skippy le Grand Gourou

Answers:


374

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

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

(请注意,SVG内容需要转义才能正常工作,例如#,用替换%23。)

这在IE 9(支持SVG)中有效。数据URL也可以在IE的较早版本中使用(有限制),但是它们本身并不支持SVG。


8
似乎可以正常使用的唯一浏览器是Safari(5.1.4)。在Opera 11.62中,渐变是黑色,在IE 9和Firefox 12中,渐变是白色。在Chrome 19中,除非您以%单位指定SVG的宽度/高度,否则它可以工作。我会说这比真正的功能更奇怪。不过,这是一个很酷的发现。
toniedzwiedz 2012年

4
是的...当我给同事看一个像这样的可爱小怪物时,我仍然很想看到同事脸上的表情,所以再次感谢您展示它的可能性。我只是去了标准规范,并说这几乎是不可能的,事实证明这是一个错误(有点)
toniedzwiedz 2012年

18
这里的“浏览器不兼容性”主要是缺少适当的URL转义,所有内容url()都应转义为url。有关在Opera,Firefox和Safari中正常运行的示例,请参见jsfiddle.net/6WAtQ
ErikDahlström'5

3
base64编码的svg与非base64之间有兼容性差异吗?Base64的腌我的CSS文件,我在刚使用在线svgs在想..
enapupe

4
注意,指定字符集的标准方法是使用“; charset = UTF-8”而不是“; utf8”。tools.ietf.org/html/rfc2397
Keith Shaw

240

有点晚了,但是如果你们中的任何一个试图使用内联SVG作为背景已经变得疯狂,上面的转义建议就不太奏效了。首先,它在IE中不起作用,根据SVG的内容,该技术会在其他浏览器(例如FF)中引起麻烦。

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

CSS现在看起来像这样:

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

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

base64更好地工作的原因是它消除了单引号和双引号以及url转义的所有问题

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

设置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>

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

有关使用SVG的更好的文章之一,位于:http : //dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/

希望这可以帮助

麦克风


2
谢啦。使用Base64的解决方案效果极佳,而我在接受可接受的答案时遇到了麻烦。
Marcel

1
你救了我的命。我有一个在chrome中工作但在FF上工作的SVG边框图像。现在可以了!:D
Papipo 2014年

也为我提供了帮助(在浪费时间尝试接受的答案之后)-这绝对是接受的答案。
卡泰伊

如果这仍然不适合您-确保在对base64进行编码之前xmlns属性设置为svgelement 例如<svg xmlns="http://www.w3.org/2000/svg">...</svg>当svg直接在HTML中时,浏览器有时会在没有它的情况下对其进行分块-情况并非如此:)
jave.web

如果6年后仍有人在看这个答案:您可能不应该使用base64 SVG css-tricks.com/probably-dont-base64-svg
Volker E.

38

对于仍在挣扎中的人们,我设法使它在所有现代浏览器IE11及更高版本上都能正常工作。

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

您需要注意三件事:

  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%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%2Csvg% 3E


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

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


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

    NOT fill =“#FF0000”
    fill =“ rgb(255,0,0)”

就我而言,我使用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');
   }
}

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

我能够省去整个sprite位图,并用CSS中的内联SVG替换它,事实证明,压缩后仅约25kb。因此,这是一种很好的方式来限制您的站点必须执行的请求数量,而不会膨胀CSS文件。


1
顺便说一句,纠正我,如果我错了,但rgb(255,0,0)应该rgb(255%2C0%2C0)一旦编码就可以了。
2016年

1
我的意思是我不编码RGB字符串,但它仍然有效。但是像您提到的那样编码可能更好。
戴维·贝特

1
好吧,实际上,我刚刚在Firefox中进行了测试并%23ff0000可以正常工作#ff0000
Capsule

1
@Capsule我不知道发生了什么,但是%23ff0000是在Chrome和FF上都适用的唯一方法。#ff0000不起作用,RGB(255,0,0)和rgb(255%2C0%2C0)方法也不起作用。
Ideogram 2013年

1
一种需要较少编码的方法(包括SCSS代码):codepen.io/jakob-e/pen/doMoML
Sphinxxx '17

26

在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;"

在Mac OS X上进行了测试。通过这种方式,您还可以避免URL转义。

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


2
致读者:请评论您的意见,而不只是投下反对票,以便您的合作可以改善此答案!在这样的问答站点中,协作至关重要。谢谢!
2015年

2
@LorDex您在评论中提供的链接与我的回答相同:)
araks'Apr 16'18

10

我派出了CodePen演示,该演示在将嵌入式SVG嵌入CSS时也遇到了同样的问题。与SCSS一起使用的解决方案是构建一个简单的url编码功能。

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

然后,只需更换%<>"'%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;
}

image-inlineCompass中还提供了一个辅助功能,但是由于CodePen不支持该功能,因此该解决方案可能会很有用。

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


1
我还创建了一支笔,让您的SVG字符串转换成适当的CSS背景值: s.codepen.io/LukyVj/debug/693cbcc30258bf67b8c30047cce060eb 所以,基本上,你粘贴<svg><path></svg>到顶部textarea的,它会直接输出消毒路径在一个url()值之内。
LukyVj

1
这很棒。谢谢。一注。您需要使用; charset = utf8使其在IE中起作用。
Daniel Lefebvre'5

4

来自第三方的内联SVG(例如Google图表)可能xmlns="http://www.w3.org/2000/svg"在SVG元素中不包含XML名称空间属性()(或者一旦呈现SVG便将其删除-浏览器检查器和来自浏览器控制台的jQuery命令都不会在SVG元素中显示名称空间)。

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


4

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

SVG图标呈现所需的功能:

  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>

另一种解决方案是使用url编码

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 using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.