问题描述
是否可以在CSS中使用内联SVG定义?
我的意思是:
.my-class {
background-image: <svg>...</svg>;
}
最佳解决方案
是的,这是可能的。尝试这个:
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内容需要为url-escaped才能正常工作,例如#被%23替代。)
This works in IE 9 (which supports SVG)。 Data-URLs在旧版本的IE中工作(有限制),但是它们本身不支持SVG。
次佳解决方案
有点迟了,但是如果你们中的任何一个人都疯狂地尝试使用内置SVG作为背景,上面的转义建议并不会奏效。一个,它在IE中不起作用,根据SVG的内容,该技术会在其他浏览器(如FF)中引起麻烦。
如果您对svg进行base64编码(而不是整个url,只是svg标签及其内容!),它可以在所有浏览器中运行。这是在base64中相同的jsfiddle示例:http://jsfiddle.net/vPA9z/3/
CSS现在看起来像这样:
body { background-image:
url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+PGxpbmVhckdyYWRpZW50IGlkPSdncmFkaWVudCc+PHN0b3Agb2Zmc2V0PScxMCUnIHN0b3AtY29sb3I9JyNGMDAnLz48c3RvcCBvZmZzZXQ9JzkwJScgc3RvcC1jb2xvcj0nI2ZjYycvPiA8L2xpbmVhckdyYWRpZW50PjxyZWN0IGZpbGw9J3VybCgjZ3JhZGllbnQpJyB4PScwJyB5PScwJyB3aWR0aD0nMTAwJScgaGVpZ2h0PScxMDAlJy8+PC9zdmc+");
记住在转换为base64之前删除任何转义的URL。换句话说,上面的例子显示颜色= ‘#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/
希望这可以帮助
麦克风
第三种解决方案
对于仍在努力的人们,我设法让所有现代浏览器IE11及以上版本都能正常工作。
base64对我而言是不可取的,因为我想使用SASS根据任何给定的颜色生成SVG图标。例如:@include svg_icon(heart, #FF0000);这样我可以创建任何颜色的某个图标,只需要在CSS中嵌入一次SVG形状。 (使用base64,您必须将SVG嵌入到您要使用的每种颜色中)
你需要注意的事情有三件事:
-
URL ENCODE您的SVG如其他人所建议的,您需要对整个SVG字符串进行URL编码,以使其在IE11中工作。在我的情况下,我在
fill="#00FF00"和stroke="#FF0000"等字段中省略了颜色值,并用SASS变量fill="#{$color-rgb}"替换,这样可以用我想要的颜色代替。您可以使用any online converter对字符串的其余部分进行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%2Fsvg%3E
-
OMIT数据URL中的UTF8 CHARSET创建数据URL时,需要省略其在IE11中工作的字符集。不是background-image:url(data:image /svg + xml; utf-8,%3Csvg%2 ….)但是background-image:url(data:image /svg + xml,%3Csvg%2 ….)
-
USE RGB() INSTEAD OF HEX颜色Firefox在SVG代码中不喜欢#。所以你需要用RGB替换你的颜色十六进制值。 NOT fill = “#FF0000” BUT 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从不在这种情况下),但是对于只有几种颜色的平面图标,这真的很好用。
我可以省略一个完整的精灵位图,并将其替换为CSS中的内联SVG,压缩之后只有25kb左右。所以这是一个很好的方式来限制网站的请求量,而不会使你的CSS文件膨胀。
第四种方案
您可以使用此简单的bash命令,将SVG文件轻松转换为CSS background属性的base64 ecoded值:
echo "background: transparent url('data:image/svg+xml;base64,"$(openssl base64 < path/to/file.svg)"') no-repeat center center;"
在Mac OS X上测试。这样你也可以避免URL转义的混乱。
请记住,base64编码SVG文件会增加其大小,请参阅css-tricks.com blog post
第五种方案
我已经分发了一个CodePen演示程序,将嵌入式SVG嵌入到CSS中也是一样的。与SCSS协同工作的解决方案是构建简单的url-encoding功能。
可以从内置 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;
}
Compass中还提供了一个image-inline辅助功能,但由于它在CodePen中不受支持,因此该解决方案可能很有用。
CodePen演示:http://codepen.io/terabaud/details/PZdaJo/
参考文献
注:本文内容整合自Google/Baidu/Bing辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。