是否可以在 CSS 中使用内联 SVG 定义?
我的意思是:
.my-class {
background-image: <svg>...</svg>;
}
<img>
标记和其他情况,请参阅 background image SVG with mask using external image not working,特别是 restrictions on SVG used as an image。
对的,这是可能的。尝试这个:
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 内容进行 url 转义才能使其正常工作,例如 #
被替换为 %23
。)
This works in IE 9 (which supports SVG)。数据 URL 也适用于旧版本的 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 转义。换句话说,上面的例子显示color='#fcc'转换为color='%23fcc',你应该回到#。
base64 效果更好的原因是它消除了单引号和双引号以及 url 转义的所有问题
如果您使用的是 JS,您可以使用 window.btoa()
来生成您的 base64 svg;如果它不起作用(它可能会抱怨字符串中的无效字符),您可以简单地使用 https://www.base64encode.org/。
设置 div 背景的示例:
var mySVG = ""; var mySVG64 = window.btoa(mySVG); document.getElementById('myDiv').style.backgroundImage = "url('data:image/svg+xml;base64," + mySVG64 + "')"; html,正文,#myDiv { 宽度:100%;高度:100%;边距:0; }
使用 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 编码您的 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%2Fsvg%3E
省略数据 URL 中的 UTF8 字符集 创建数据 URL 时,您需要省略字符集以使其在 IE11 中工作。不是背景图像:url(数据:图像/svg+xml;utf-8,%3Csvg%2....)但是背景图像:url(数据:图像/svg+xml,%3Csvg%2... .)
使用 RGB() 代替十六进制颜色 Firefox 不喜欢 SVG 代码中的 #。因此,您需要将颜色十六进制值替换为 RGB 值。不填充="#FF0000" 但填充="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 文件膨胀。
rgb(255,0,0)
应该变成 rgb(255%2C0%2C0)
。
%23ff0000
在 Firefox 中对 #ff0000
运行良好
我的解决方案是https://yoksel.github.io/url-encoder/您只需插入 svg 并取回背景图像代码
background-size: cover
属性,并且 svg 似乎与其容器成比例地伸展。
在 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 blog post。
我已经分叉了一个 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;
}
Compass 中还有一个 image-inline
辅助函数,但由于 CodePen 不支持它,因此该解决方案可能有用。
CodePen 上的演示:http://codepen.io/terabaud/details/PZdaJo/
<svg><path></svg>
粘贴到顶部文本区域,它会直接在 url()
中输出经过清理的路径价值。
我找到了一种 SVG 解决方案。但这仅适用于 Webkit,我只想与您分享我的解决方法。在我的示例中,展示了如何通过过滤器将 DOM 中的 SVG 元素用作背景(背景图像:url('#glyph')不起作用)。
此 SVG 图标渲染所需的功能:
使用 CSS 将 SVG 滤镜效果应用于 HTML 元素(IE 和 Edge 不支持)feImage 片段加载支持(firefox 不支持)
.test { /* 背景图片: url('#glyph');背景尺寸:100% 100%;*/ 过滤器:url(#image);高度:100px;宽度:100 像素; } .test:before { display:block;内容:'';颜色:透明; } .test2{ 宽度:100px;高度:100px; } .test2:before { display:block;内容:'';颜色:透明;过滤器:网址(#image);高度:100px;宽度:100 像素; }
另一种解决方案是使用 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{ 高度:50px;宽度:250px;显示:块;背景位置:中心中心;背景重复:不重复;背景尺寸:包含; }
来自第 3 方来源(如 Google 图表)的内联 SVG 可能在 SVG 元素中不包含 XML 命名空间属性 (xmlns="http://www.w3.org/2000/svg"
)(或者可能在呈现 SVG 后将其删除 - 浏览器检查器和浏览器控制台中的 jQuery 命令都不会显示 SVG 中的命名空间元素)。
当您需要将这些 svg 片段重新用于您的其他需求(CSS 中的背景图像或 HTML 中的 img 元素)时,请注意缺少的命名空间。没有命名空间的浏览器可能会拒绝显示 SVG(不管编码是 utf8 还是 base64)。
根据已经提到的 https://github.com/yoksel/url-encoder/ 采用的方法以编程方式完成:
// Svg (string) const hexagon = `
如果您使用的是 postcss,您可以尝试 postcss-inline-svg
插件 https://www.npmjs.com/package/postcss-inline-svg
.up {
background: svg-load('img/arrow-up.svg', fill: #000, stroke: #fff);
}
.down {
background: svg-load('img/arrow-down.svg', fill=#000, stroke=#fff);
}
你也可以这样做:
url()
中的所有内容都应该进行 url 转义。有关在 Opera、Firefox 和 Safari 中运行良好的示例,请参见 jsfiddle.net/6WAtQ。