一个相当不错的 SVG 图标系统

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 价值 200 美元的免费积分!

我一直主张使用 SVG 图标系统,现在依然如此。简单说来,它有很多优点:基于矢量的图标在高像素密度世界中看起来很棒,SVG 提供了大量的设计控制,并且它们的可预测性和性能也很高。

我还经常提倡使用基于 <symbol> (“SVG 雪碧图”)和 <use> 元素放置它们的 SVG 图标系统。我改变了一些想法。我认为这并不是一个糟糕的方法,但肯定存在一个更简单(也许也更好)的方法。

直接将图标嵌入代码中。

就是这样。如果您希望看到更复杂的方法,请原谅。

就像这样

<button>
  <svg class="icon icon-cart" viewBox="0 0 100 100" aria-hidden="true">
    <!-- all your hot svg action, like: -->
    <path d=" ... " />
  </svg>
  Add to Cart
</button>

或者更实际一点,使用您选择的服务器端包含

<button>
  <?php include("/icons/icon-cart.svg"); ?>
  Add to Cart
</button>

就像我说的

优点 #1:无需构建过程

您无需任何花哨的工具来实现这一点。您的包含大量 SVG 图标的文件夹仍然是一个包含大量 SVG 图标的文件夹。您可能需要优化它们,但仅此而已。

优点 #2:没有 Shadow DOM 问题

作为 <use> 引用包含的 SVG 图标具有 Shadow DOM 边界。

在 Chrome DevTools 中显示 Shadow DOM 边界

这很容易造成混淆。例如

var playButton = document.querySelector("#play-button-shape");

playButton.addEventListener("click", function() {
  alert("test");
});

这将无法正常工作。您将定位 <symbol> 中的路径,这实际上不会做任何事情,而且点击处理程序会在克隆过程中丢失。您必须将类似的处理程序附加到父 <svg>,例如 #play-button

同样,类似这样的 CSS 选择器

.button #play-button-shape {

}

将不会选择任何内容,因为这两者之间存在 Shadow DOM 边界。

当您直接将内联 SVG 放入适当位置时,将不会存在 Shadow DOM 边界。

优点 #3:仅使用您需要的图标

<use>/<symbol> 系统中,您有这个 SVG 雪碧图,它很可能包含在每个页面上,无论它们是否在任何给定页面上都被使用。当您直接包含内联 SVG 时,页面上的唯一图标是您实际使用的图标。

我将此列为一个优点,但这有点两面性。公平地说,可以缓存 SVG 雪碧图(例如,使用 Ajax 获取并注入页面),这将非常高效。

这是一个有点棘手的问题。<use> 本身与缓存无关,它与 <use> 所引用的 SVG 的位置有关。如果雪碧图是使用 Ajax 获取的,则可以缓存它。如果雪碧图只是 HTML 的一部分,则可以缓存该 HTML。或者 <use> 可以指向一个外部文件,并且可以缓存该文件。这很有吸引力,但是…

优点 #4:没有跨浏览器支持问题

IE 或 Edge 浏览器无法做到这一点

<use xlink:href="/icons/sprite.svg#icon-cart" />

也就是说,通过相对文件路径链接到图标。它在 Microsoft 环境中唯一可行的方法是引用同一页面上的 SVG 的 ID。为此有一些变通方法,例如使用 Ajax 获取雪碧图并将其转储到页面上,或者使用像SVG for Everybody 这样的库,该库检测浏览器支持情况,并根据需要使用 Ajax 获取所需的部分 SVG 并注入它。

潜在的小问题:HTML 缓存膨胀

如果您最终使用了雪碧图路线,就像我说的,您可能会很想使用相对路径链接到雪碧图,以利用缓存优势。但 Microsoft 浏览器会破坏这一点,因此您需要在以下两种选择之间做出选择:

  1. JavaScript 解决方案,例如使用 Ajax 获取整个雪碧图并将其注入,或使用 polyfill。
  2. 在服务器端将雪碧图转储到 HTML 中。

我发现自己更经常做 #2,因为 #1 会导致异步加载图标,这感觉很卡。但使用 #2 意味着“膨胀的”HTML 缓存,这意味着这个雪碧图在每个唯一的 HTML 页面上被缓存了一遍又一遍,效率不高。

直接内联 SVG 也会出现同样的情况。


结论和 TLDR:由于其简单性、优势和微不足道的缺点,我预计直接内联 SVG 图标将成为处理 SVG 图标系统最流行的方式。