377

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

我的意思是:

.my-class {
  background-image: <svg>...</svg>;
}
4

11 回答 11

515

是的,有可能。试试这个:

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 转义才能正常工作,例如#替换为%23.)

这适用于 IE 9(支持 SVG)。数据 URL 也适用于旧版本的 IE(有限制),但它们本身并不支持 SVG。

于 2012-05-26T18:09:19.330 回答
306

有点晚了,但是如果你们中的任何一个人一直在疯狂地尝试使用内联 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 = "<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/

希望这可以帮助

麦克风

于 2014-02-07T11:34:24.257 回答
44

对于仍在苦苦挣扎的人,我设法让它在所有现代浏览器 IE11 及更高版本上运行。

base64 对我来说是没有选择的,因为我想使用 SASS 根据任何给定的颜色生成 SVG 图标。例如:@include svg_icon(heart, #FF0000);这样我可以创建任何颜色的特定图标,并且只需在 CSS 中嵌入一次 SVG 形状。(使用 base64,您必须将 SVG 嵌入到您想要使用的每种颜色中)

您需要注意三件事:

  1. 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%23m257.063%200c127.06%200%2021.808%20105.33%2021.808%20235.260%%2041.012%2013.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%vsg%3E2% 3E


  1. 省略数据 URL 中的 UTF8字符集 创建数据 URL 时,您需要省略字符集以使其在 IE11 中工作。

    不是背景图像:url(数据:图像/svg+xml;utf-8,%3Csvg%2....)
    但是背景图像:url(数据:图像/svg+xml,%3Csvg%2... .)


  1. 使用 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 文件膨胀。

于 2016-06-07T15:41:06.017 回答
32

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

于 2015-03-04T22:11:30.173 回答
26

我的解决方案是https://yoksel.github.io/url-encoder/ 您只需插入您的 svg 并取回背景图像代码

于 2020-08-05T10:50:56.253 回答
11

我已经分叉了一个 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/

于 2016-02-04T14:57:00.927 回答
5

我找到了一种 SVG 解决方案。但这仅适用于 Webkit,我只想与您分享我的解决方法。在我的示例中,展示了如何通过过滤器将 DOM 中的 SVG 元素用作背景(背景图像:url('#glyph')不起作用)。

此 SVG 图标渲染所需的功能:

  1. 使用 CSS 将 SVG 滤镜效果应用于 HTML 元素(IE 和 Edge 不支持)
  2. 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>

于 2017-08-11T08:58:29.037 回答
4

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

当您需要将这些 svg 片段重新用于您的其他需求(CSS 中的背景图像或 HTML 中的 img 元素)时,请注意缺少的命名空间。没有命名空间的浏览器可能会拒绝显示 SVG(不管编码是 utf8 还是 base64)。

于 2015-06-26T20:46:49.603 回答
1

根据已经提到的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"/>

于 2021-03-06T22:11:00.777 回答
1

如果您使用的是 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);
}
于 2021-06-23T01:02:22.290 回答
-3

你也可以这样做:

<svg viewBox="0 0 32 32">
      <path d="M11.333 13.173c0-2.51 2.185-4.506 4.794-4.506 2.67 0 4.539 2.053 4.539 4.506 0 2.111-0.928 3.879-3.836 4.392v0.628c0 0.628-0.496 1.141-1.163 1.141s-1.163-0.513-1.163-1.141v-1.654c0-0.628 0.751-1.141 1.419-1.141 1.335 0 2.571-1.027 2.571-2.224 0-1.255-1.092-2.224-2.367-2.224-1.335 0-2.367 1.027-2.367 2.224 0 0.628-0.546 1.141-1.214 1.141s-1.214-0.513-1.214-1.141zM15.333 23.333c-0.347 0-0.679-0.143-0.936-0.404s-0.398-0.597-0.398-0.949 0.141-0.689 0.398-0.949c0.481-0.488 1.39-0.488 1.871 0 0.257 0.26 0.398 0.597 0.398 0.949s-0.141 0.689-0.398 0.949c-0.256 0.26-0.588 0.404-0.935 0.404zM16 26.951c-6.040 0-10.951-4.911-10.951-10.951s4.911-10.951 10.951-10.951c6.040 0 10.951 4.911 10.951 10.951s-4.911 10.951-10.951 10.951zM16 3.333c-6.984 0-12.667 5.683-12.667 12.667s5.683 12.667 12.667 12.667c6.984 0 12.667-5.683 12.667-12.667s-5.683-12.667-12.667-12.667z"></path>
</svg>

于 2020-07-21T19:53:10.027 回答