Learning to be Giant.

使用SVG Sprite替代iconfont

|

iconfont如今已经成为了前端必备的工具,它的样式调整非常方便,使用很直观,而且再多分辨率情况下能够良好的展示和适配。然而,它也有它的不足之处,例如其颜色的填充仅限于单色,无法支持包含多种颜色的图标;在不同浏览器下展现的效果可能有所不同,在某些浏览器下可能会出现锯齿效果等等。与此同时,SVG正被越来越多的主流浏览器支持,并且在各浏览器当中的显示效果一致,所以尝试使用SVG来替代iconfont是一个不错的选择。

我们知道前端性能优化中常用CSS Sprite来减少HTTP Request,相同的道理,我们也希望能够使用SVG Sprite来实现同样的目的。

创建SVG Sprite

SVG创建的方法十分简单。我们知道CSS Sprite就是将所有的图片整合到一幅图片当中,SVG Sprite同理。在百姓网,我们前端采用的图标库Baicons由许许多多的.svg文件组成,我们所需要做的就是讲所有这些.svg文件复制粘贴到同一个文件当中,就像这样:

<?xml version=“1.0” encoding=“utf-8”?>
<!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN” “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”>

<svg xmlns=“http://www.w3.org/2000/svg”>
  <symbol id=“icon-android” viewBox=“0 0 72 72”>
    <!— 路径/图形 —>  
  </symbol>
  <symbol id=“icon-apple” viewBox=“72 0 72 72”>
    <!— 路径/图形 —>  
  </symbol>
</svg>

我们在我们的图标集中有几十个这样的图标,我们当然不需要手动一个个去操作,这里推荐大家可以使用gulp-svgstore,如果使用Grunt的话可以使用grunt-svgstore。构建工具可以自动生成我们需要的sprite文件。

使用SVG Sprite

SVG Sprite的使用也非常的简单,只需要在需要的地方插入:

<svg>
	<use xlink:href=“sprite.svg#icon-android” />
</svg>

就可以轻松地使用了。由于我们使用的是SVG,我们可以使用CSS指定它的样式,比如设定大小、填充色等等,十分方便。

兼容性问题

虽然SVG Sprite使用十分的方便,但是非常遗憾的是并不是所有的浏览器都能够完美支持这一个功能。首先,一些浏览器不支持inline SVG特性:

On the browser support front, the danger zones are IE 8 and down, Safari 5 and down, iOS 4.3 and down, and Android 2.3 and down.<a href=“#1”>1</a>

根据Caniuse部分浏览器不支持SVG fragment identifiers特性。

同时,一些支持inline SVG特性的浏览器,却不支持external svg特性,这使得无法使用浏览器的cache来优化前端性能,例如IE9/10。针对类似的情况,我们尝试采用PNG fallback,方法也十分简单,我们fallback到CSS Sprite:

<svg>
	<switch>
		<use xlink:href=“sprite.svg#icon-android” />
		<foreignObject>
			<i class=“icon-android”></i>
		</foreignObject>
	</switch>
</svg>

这种方式对于IE8及以下这些不支持inline SVG的浏览器适用,对于IE9/10这种支持inline SVG却不支持external SVG的浏览器会失效。目前看到的比较好的解决方法是采用ajax,但是相对而言也比较麻烦:Ajaxing for your SVG Sprite

总结

SVG Sprite是一个非常好的图标的技术,但是目前浏览器支持还不完全,希望以后慢慢变好吧。

参考文章

  1. <a id=“1”></a>Icon System with SVG Sprites
  2. SVG symbol a Good Choice for Icons
  3. How to Implement Cross-Browser SVG Sprites

Disclaimer: This is a personal weblog. The opinions expressed here represent my own and not those of any entity with which I have been, am now, or will be affiliated.

Comments