使用 SVG 打造一个高质量的 ICON 系统

2,079 阅读4分钟
原文链接: svgtrick.com

一直以来,我都是提倡使用SVG来构建icon系统,现在依然如此。主要原因有以下几点:

1、矢量,可以适应任意分辨率的设备;

2、SVG提供了很多的接口,可定制性强,性能也比较好。

我也一直提倡使用symboluse的方式即所谓的SVG sprite来使用SVG构建icon系统。不过,现在我有些新的看法,虽然这种方法是一种很不错的方法,但是,我认为应该还有更简单的方法来使用SVG构建icon系统。

下面就来聊聊这种也许是更简单的方法。

直接使用inline的方法使用SVG

inline方法即直接把SVG插入到html中:

<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>

或者是直接在服务端插入SVG,也是一个不错的选择:

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

那使用这种方法有哪些优势呢?

优点1、不需要做额外的工作

直接导出SVG,然后放入到html中就可以了,就是这么简单。仅仅需要在使用之前优化一下SVG文件的就可以了。

优点2、没有Shadow DOM的干扰

如果使用use的方法来使用SVG,它会有一个shadow boundary

这样就会导致一些额外的问题,比如:

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

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

你会发现,点击事件没有生效。那是因为shadow boundary,保证主 DOM 写的 CSS 选择器和 JavaScript 代码都不会影响到Shadow DOM,当然也保护主文档不受 shadow DOM 样式的侵袭。所以直接给use方式引用的SVG绑定点击事件不会生效。为了使点击事件生效,不得不把事件绑定在引用SVG元素的父级元素上,比如#play-button

同样CSS也要做相应的一些修改:

.button #play-button-shape {

}

如果是直接把SVG代码插入到DOM元素中,则没有 Shadow DOM 这个问题。

优点3、按需所取

如果使用SVG sprite的方法来使用SVG,则不得不在每一个页面都包含一整个的icon,不管它们有没有在页面中使用到。而使用inline方法,则只需要在需要的地方引入对应的SVG就行了。

当然,这个优点也许过于牵强。你也可以说使用SVG sprite的文件可以被缓存起来,比如这里就是一种不错的方法。而use因为没有做任何的事情,只是引用一下SVG而已,所以不能被缓存。当SVG sprite是使用Ajax方式来引入的话,可以被缓存起来。即使SVG sprite是直接插入到html中,也可以被缓存。或者当use引用的是外部文件,也可以被缓存。

优点4、不用考虑浏览器兼容问题

现代浏览器几乎都支持SVG,就算是IE或者是Edge也可以通过下面的方法来引用SVG:

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

也可以使用 SVG for Everybody 这个库,它可以很好的根据浏览器对SVG的支持情况来使用不同的方法使用SVG。

聊聊缓存问题

如上所说,使用 SVG sprite 的方法的确很诱人,因为可以被缓存。不过,微软系的浏览器却不允许这么做,为了应对微软系的浏览器,有两种选择:

1、JavaScript方案,比如使用Ajax的方法动态插入 SVG sprite 或者是使用第三方提供的 polyfill 来解决这个问题。

2、将 SVG sprite 缓存在服务端。

我使用的比较多的是第二种方案,因为第一种方案是使用异步的方法来加载SVG文件,感觉非常奇怪。如果是使用第二种方案的话,也有一个问题,因为要在每一个不同的页面缓存 SVG sprite ,所以在效率上会有影响。

说到底,还是直接在页面中使用SVG即 inlining SVG 方法更简单。

综上所述,我觉得inlining SVG这种SVG icon 构建方法将会变得越来越流行。

本文主要是从A Pretty Good SVG Icon System这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!