是否可以在CSS中使用内联SVG定义?
我的意思是:
.my-class {
background-image: <svg>...</svg>;
}
是否可以在CSS中使用内联SVG定义?
我的意思是:
.my-class {
background-image: <svg>...</svg>;
}
当前回答
我找到了SVG的一个解决方案。但这只是Webkit的工作,我只是想与你分享我的工作方法。在我的例子中展示了如何使用SVG元素从DOM作为背景通过过滤器(background-image: url('#glyph')是不工作的)。
SVG图标渲染所需的特性:
将SVG筛选效果应用到HTML元素使用CSS (IE和 边缘不支持) 支持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>
其他回答
我在CodePen演示中也遇到了将内联SVG嵌入CSS的问题。使用SCSS的解决方案是构建一个简单的url编码函数。
字符串替换函数可以从内置的str-slice, str-index函数中创建(参见css-tricks,感谢Hugo Giraudel)。
然后,用%xxcodes替换%,<,>,",':
@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不支持它,因此这个解决方案可能会有用。
CodePen上的演示:http://codepen.io/terabaud/details/PZdaJo/
是的,这是可能的。试试这个:
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取代。)
这可以在IE 9(支持SVG)中工作。数据url在旧版本的IE中也可以工作(有限制),但它们本身不支持SVG。
基于已经提到的https://github.com/yoksel/url-encoder/所采取的方法以编程方式完成:
// Svg (string) const hexagon = ` <svg width="100" height="20" viewBox="0 0 100 20" xmlns="http://www.w3.org/2000/svg"> <defs> <linearGradient id="redyel" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="1" y2="1" > <stop offset="0%" stop-color="#ff0000" /> <stop offset="100%" stop-color="#ffff00" /> </linearGradient> </defs> <polygon points="0,10 5,0 95,0 100,10 95,20 5,20" fill="#eee" stroke="url(#redyel)" /> </svg> ` // svgToBackgroundImage const symbols = /[%#()<>?[\\\]^`{|}]/g; const newLine = /\r?\n/; const notEmptyString = (str) => str.length; const trim = (str) => str.trim(); const toOneLine = (str) => str.split(newLine).filter(notEmptyString).map(trim).join(" "); function addNameSpace(svgString) { if (svgString.indexOf(`http://www.w3.org/2000/svg`) < 0) { svgString = svgString.replace( /<svg/g, `<svg xmlns="http://www.w3.org/2000/svg"` ); } return svgString; } function encodeSVG(svgString) { svgString = svgString.replace(/>\s{1,}</g, `><`); svgString = svgString.replace(/\s{2,}/g, ` `); // Using encodeURIComponent() as replacement function // allows to keep result code readable return svgString.replace(symbols, encodeURIComponent); } const svgToBackgroundImage = (svgString) => `url('data:image/svg+xml,${encodeSVG(addNameSpace(toOneLine(svgString)))}')`; // DOM const element = document.querySelector("#hexagon"); element.style.backgroundImage = svgToBackgroundImage(hexagon); #hexagon { width: 100px; height: 20px; } <div id="hexagon"/>
如果你们中有人疯狂地试图使用内联SVG作为背景,那么上面的转义建议就不太管用了。首先,它不能在IE中工作,而且取决于SVG的内容,该技术在其他浏览器(如FF)中会造成麻烦。
如果base64编码svg(不是整个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 = "<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/
在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的博客文章。