Inline SVG in CSS
是否可以在CSS中使用内联SVG定义?
我的意思是:
1 2 3 | .my-class { background-image: <svg>...</svg>; } |
对的,这是可能的。尝试这个:
1 2 3 | 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>"); } |
- http://jsfiddle.net/6WAtQ/
(请注意,SVG内容需要转义才能正常工作,例如
这在IE 9(支持SVG)中有效。数据网址也可以在IE的较早版本中使用(有限制),但它们本身并不支持SVG。
有点晚了,但是如果您中的任何一个都想使用内联SVG作为背景变得疯狂,那么上面的转义建议就不太奏效了。一方面,它在IE中不起作用,并且根据您SVG的内容,该技术会在其他浏览器(例如FF)中引起麻烦。
如果您对svg(不是整个url,仅是svg标记及其内容!)进行base64编码,则它可在所有浏览器中使用。这是base64中相同的jsfiddle示例:http://jsfiddle.net/vPA9z/3/
CSS现在看起来像这样:
1 2 | body { background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PGxpbmVhckdyYWRpZW50IGlkPSdncmFkaWVudCc+PHN0b3Agb2Zmc2V0PScxMCUnIHN0b3AtY29sb3I9JyNGMDAnLz48c3RvcCBvZmZzZXQ9JzkwJScgc3RvcC1jb2xvcj0nI2ZjYycvPiA8L2xpbmVhckdyYWRpZW50PjxyZWN0IGZpbGw9J3VybCgjZ3JhZGllbnQpJyB4PScwJyB5PScwJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJy8+PC9zdmc+"); |
在转换为base64之前,请记住删除所有URL转义。换句话说,上面的示例显示color ='#fcc'转换为color ='%23fcc',您应该回到#。
base64更好地工作的原因是它消除了单引号和双引号以及url转义的所有问题
如果您使用的是JS,则可以使用
设置div背景的示例:
1 2 3 | 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 +"')"; |
1 2 3 4 5 | html, body, #myDiv { width: 100%; height: 100%; margin: 0; } |
1 |
使用JS,您可以即时生成SVG,甚至可以更改其参数。
有关使用SVG的更好的文章之一,位于:http://dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/
希望这可以帮助
麦克风
对于仍在挣扎中的人们,我设法使它在所有现代浏览器IE11及更高版本上都能正常工作。
base64对我来说是没有选择的,因为我想使用SASS根据任何给定的颜色生成SVG图标。例如:
您需要注意三件事:
URL编码您的SVG
正如其他人所建议的那样,您需要对整个SVG字符串进行URL编码,以使其在IE11中起作用。就我而言,我在诸如
%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%3E%3C%2Fsvg% 3E
在数据URL中省略UTF8字符集创建数据URL时,您需要省略字符集,以使其在IE11中起作用。
不是背景图片:url(data:image / svg + xml; utf-8,%3Csvg%2 ....)
但是背景图片:url(data:image / svg + xml,%3Csvg%2 ....)
使用RGB()代替十六进制颜色Firefox不喜欢SVG代码中的#。因此,您需要用RGB替换颜色十六进制值。
NOT fill ="#FF0000"
但是fill =" rgb(255,0,0)"
就我而言,我使用SASS将给定的十六进制转换为有效的rgb值。如评论中所指出的,最好也对URL RGB字符串进行URL编码(因此逗号变为%2C)
1 2 3 4 5 6 | @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文件。
在Mac / Linux上,您可以使用以下简单的bash命令轻松地将SVG文件转换为CSS背景属性的base64编码值:
1 | 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博客文章。
我派出了CodePen演示,该演示在将嵌入式SVG嵌入CSS时也遇到了同样的问题。与SCSS一起使用的解决方案是构建一个简单的url编码功能。
可以从内置的str-slice,str-index函数创建字符串替换函数(感谢Hugo Giraudel,请参阅css-tricks)。
然后,只需将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @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; } |
Compass中还提供了一个
关于CodePen的演示:http://codepen.io/terabaud/details/PZdaJo/
来自第三方资源(例如Google图表)的内联SVG可能在SVG元素中不包含XML名称空间属性(
当您需要将这些svg代码片段重新用于其他需求时(CSS中的背景图片或HTML中的img元素)请注意缺少的名称空间。如果没有名称空间,浏览器可能会拒绝显示SVG(与utf8或base64编码无关)。
我找到了SVG的一种解决方案。但这仅适用于Webkit,我只想与您分享我的解决方法。在我的示例中,展示了如何通过过滤器将DOM中的SVG元素用作背景(background-image:url('#glyph')无法正常工作)。
SVG图标呈现所需的功能:
边缘不支持)
支持)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | .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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <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> |
另一种解决方案是使用url编码
1 2 3 4 | 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)})`; |
1 2 3 4 5 6 7 8 | .container{ height:50px; width:250px; display:block; background-position: center center; background-repeat: no-repeat; background-size: contain; } |
1 2 3 | <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> |