2023-11-18 06:00:02

CSS中的内联SVG

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

我的意思是:

.my-class {
  background-image: <svg>...</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"/>

其他回答

在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的博客文章。

对于那些仍在挣扎的人,我设法让它在所有IE11及以上的现代浏览器上工作。

base64不适合我,因为我想使用SASS根据任何给定的颜色生成SVG图标。例如:@include svg_icon(heart, #FF0000);这样我就可以用任何颜色创建特定的图标,并且只需要在CSS中嵌入SVG形状一次。(使用base64,你必须在你想使用的每一种颜色中嵌入SVG)

有三件事你需要注意:

URL ENCODE YOUR SVG As others have suggested, you need to URL encode your entire SVG string for it to work in IE11. In my case, I left out the color values in fields such as fill="#00FF00" and stroke="#FF0000" and replaced them with a SASS variable fill="#{$color-rgb}" so these can be replaced with the color I want. You can use any online converter to URL encode the rest of the string. You'll end up with an SVG string like this: %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时,为了在IE11中工作,你需要省略该字符集。 NOT background-image: url(data:image/svg+xml;utf-8,%3Csvg%2....) BUT background-image: url(data:image/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文件。

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

当您需要为其他需要(CSS中的background-image或HTML中的img元素)重新使用这些svg片段时,请注意丢失的名称空间。如果没有名称空间,浏览器可能会拒绝显示SVG(无论编码是utf8还是base64)。

基于已经提到的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/