使用SVG图像的方法

时间:2014-11-22 13:23:30

标签: html css svg

我刚刚从Google Web Fundamentals上阅读了this article关于使用SVG图标的信息。给出了两种方法。第一种是内联方法。例如:

  <svg version="1.1" xmlns="http://www.w3.org/2000/svg"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       width="32" height="32" viewBox="0 0 32 32">
    <path d="M27 4l-15 15-7-7-5 5 12 12 20-20z" fill="#000000"></path>
  </svg>

Demo

第二种方法是使用图像标记,例如:<img src="credit.svg">

我也知道SVG可以定义为:

  • 一个对象
  • 一个嵌入式代码
  • 一个iframe

它们也可以在CSS中设置为背景图像。

我的问题:

每种方法有哪些优缺点?

3 个答案:

答案 0 :(得分:2)

使用imgobjectembed和其他SVG背景的优势:

  • <img class="icon icon_foo">比内嵌SVG - <svg class="icon icon_foo"><use xlink:href="#foo"></use></svg>
  • 短得多且漂亮

使用imgobjectembed和其他SVG背景的缺点:

  • 你完全没有任何样式选项的控制 - 你不能设置颜色,轮廓宽度和轮廓颜色 - 所有你能做的只是将SVG作为背景并在SVG文件中设置样式一次
  • 由于上面的陈述,你不能重复使用你的图标(如果你的网页上有两三二十二个不同的地方有一个图标,它应该用不同的颜色着色,唯一的方法是创建二三二十二等SVG文件只有一个区别 - 填充选项;)

使用内联SVG的优点:

  • 可重用性(例如,您只有一个Twitter SVG图标,您可以随处使用任何样式,因此,您不需要2个或3个相同的SVG文件,每个SVG文件中只有不同的填充属性)
  • 完全控制您的图标外观 - 样式,颜色,尺寸

使用内联SVG的缺点:

  • 它比IMG长,看起来不漂亮

缓存:

使用AngularJS或任何其他框架:

<ng-include src="'icons.html'"></ng-include>

使用VanillaJS:

file icons.js on your server:

var icons = '<svg><symbol id="icon-XXX" viewBox="0 0 256 256"><path d="{here_goes_compounded_path}"></path></symbol></svg>';

in HEAD section:

<script src="icons.js"></script>

<script>
    document.getElementById('icon-placeholder').innerHTML(icons);
</script>

right after the BODY tag:

<div id="icon-placeholder" style="display:none;"></div>

Fiddle采用最佳方法:

body 标记后面放置所有SVG图标(或使用Angular或任何其他框架ng-include):

<body>
    <svg style="display:none;">
        <symbol id="icon-XXX" viewBox="0 0 256 256"><path d="{here_goes_compounded_path}"></path></symbol>
        <symbol id="icon-YYY" viewBox="0 0 256 256"><path d="{here_goes_compounded_path}"></path></symbol>
    </svg>

在您网页的任何位置放置一个图标:

<svg class="icon icon_red">
    <use xlink:href="#icon-XXX"></use>
</svg>
<svg class="icon icon_green">
    <use xlink:href="#icon-YYY"></use>
</svg>
<svg class="icon icon_blue">
    <use xlink:href="#icon-XXX"></use>
</svg>

在CSS中:

.icon {
    width: 16px;
    height: 16px;
    fill: currentColor;
}
.icon_red { fill: #f00; }
.icon_green { fill: #0f0; }
.icon_blue { fill: #00f; }

.icon_foo {
    stroke: #000;
    stroke-width: 8;
    fill: #0f0;
}

不要忘记魔法&#34; currentColor&#34; CSS变量 - 它将以当前文本颜色为您的SVG图标着色:

fill: currentColor;

还必须阅读:

答案 1 :(得分:1)

答案是,如果您担心谁在查看您的代码?根据绘制的SVG的复杂程度,SVG内联将始终膨胀您的HTML。 Inline在某些方面确实具有更好的性能影响,因为它直接加载HTML而不是在使用SVG时从外部加载SVG,例如<img>。然而,它实际上并不引人注意,在表现时应该是最不重要的。

内联SVG的缺点:

  • Bloats code
  • 无法通过浏览器缓存
  • 没有后备可用
  • IE,没有XHTML(并且如果支持SVG那样)并不支持SVG 技术,虽然这是一个低优先级,我们不应该关心它在当前的网络世界。尽管如此,这对那些古代战士来说仍然是一个不利因素。

内联SVG的优点:

  • 我无法认真思考。其他爱管闲事的人可以看到吗?
  • 实际上,未启用CSS的人可以看到

<img>与SVG一起使用的缺点:

  • 同样,有限的后备支持(您可以使用Modernizr将.svg扩展名替换为.png,但是您依赖于启用了javascript的用户)
  • SVG的样式选项有限

<img>与SVG一起使用的优势:

  • 在语义上比膨胀所有代码更好
  • 代码库中的可读性更适合a)你自己和b)其他可能正在从事这个项目的开发人员。
  • 更好的可维护性。

替代方法:

您可以使用您在问题(及以下)中提供的有关使用<object><embed><iframe>的方法,但这些方法也会限制用例并需要声明在每个 HTML文档中,当您在项目中进展时,无论是大型还是小型,都会变得混乱。

更好的方法&#39;:

免责声明:对所有人来说,绝不是更好的选择。方法。这就是我如何为可重用性声明我的SVG元素,并在使用SVG时让我完全控制识别我的资产。

在HTML中使用内联SVG的最大缺陷是后备支持。我一直使用SVG作为背景图像(除非它是我用于图标等的webfont),纯粹是因为我可以创建一个.png版本并在我的CSS中编写回退,就像这样:

.icon {
    display: inline-block;
    vertical-align: baseline;
    background-repeat: no-repeat;
    background-position: center center;
    background-size: contain;
}

.icon--16 {
    width: 16px;
    height: 16px;
}

/* Always declare the PNG before the SVG. */
.icon--foo-blue {
    background-image: url('foo-blue.png'); /* Fallback */
    background-image: url('foo-blue.svg'), none; /* Modern */
}

.icon--foo-green {
    background-image: url('foo-green.png'); /* Fallback */
    background-image: url('foo-green.svg'), none; /* Modern */
}

然后,使用它:

<span class="icon icon--16 icon--foo-blue"></span>
<span class="icon icon--16 icon--foo-green"></span>

这样做的缺点:

  • 不支持CSS样式,但是,我们应该知道为什么我们在CSS中设置SVG样式。如果您使用的颜色多于您网站使用的颜色,那么通常会出现一些不正确的问题。为相同的SVG声明4个文件但颜色不同是不良做法,因为它允许我们在浏览器中将这些文件缓存在以后的任何网页中,在答案中以下构造完全消除了这个目的。利用服务器上/浏览器内的缓存!

当然,这取决于您尝试向用户呈现的图像类型。例如,如果您要使用大型SVG文件来展示某些内容,我可能会想到我定位的用户类型;那就是现代浏览器上的那些因为我可能想要包含花哨的内联SVG动画等等。

这也取决于个人偏好。到目前为止,使用SVG并没有出现重大的危险信号,但对于那些在IE9以下的石器时代,我们仍然有一些心脏。而且,不要忘记,Android也是SVG的古怪!

编辑:似乎对内联SVG存在很大争议。一句警告是,这样做没有可重用性。如果您正在展示一个花式网站,其中包含精美的SVG动画,那么请务必在SVG中构建整个页面,以便大声呼喊。没有人阻止你。这是个人喜好。但是对于图标,您很可能会在整个项目中重复使用,请在HTML之外声明它们,因为从长远来看,它会为您提供更好的控制而不是因为您需要在此处和那里使用不同的颜色。想一想。 :)

答案 2 :(得分:0)

如今,我倾向于将其包装在Web组件中:

/assets/svg/hex.js

export default `<svg>...</svg>`;

/my-svg.js

class MySvg extends HTMLElement {
  connectedCallback() {
    const id = this.getAttribute('id');
    import(`./assets/svg/${id}.js`).then(svg => {
      this.innerHTML = `
        ${svg.default}
      `;
    });
  }
}
customElements.define("my-svg", MySvg);

index.html

<my-svg id="hex"></my-svg>

这样,我就获得了内联svg的优势,由于动态导入而实现了延迟加载,而我只需要一个自定义元素就可以避免代码中的膨胀。并且id属性可以清楚显示我正在加载哪个svg。