# 图标
组件库UI组件难免会包含一些小图标,需要寻找一种合适的方式处理这些图标。
## 图片方案
想要在页面展现一些图标,传统的方式使用的就是图片,但是使用图片存在许多的弊端,主要表现是下面三个方面
1. 增加了页面的请求:我们知道每张图片都是一个请求,所以有些网站为了提高性能会使用雪碧图,把网页中比较小的一些小图片整合到一张图片文件中,再利用CSS的background-image属性插入图片,然后利用background-position属性对图片所需要的部分进行精确定位。但是它有个问题就是,雪碧图比较适合固定功能的网站。而我们的网站每隔几天就要加一个新的功能,添加和替换雪碧图是个很繁琐的工作。而且目前我们公司网站设计全部使用sktech,我都好久没打开过ps了,对于sketch来说,雪碧图位置的标识也是个挺麻烦的事情。
2. 图片的大小和颜色不容易改变:background-size是一个CSS3的属性,ie8是不支持的,所以不能够使用它来设置图片的大小,有的时候为了更加清晰,设计会给我一个二倍图,那我想让他在IE8下面正常的尺寸展示,就只能使用img标签,这种形式不仅加重了请求,而且对雪碧图很不友好。其次是颜色,这些icon 有很多时候,想要hover上去有个效果,目前必须准备两张图片,如果想改变成多个颜色,就要准备多个图片。
3. 最后一个也是近些年面临的一个问题,就是苹果的屏幕清晰度越来越高,在高像素下面,传统的位图会出现马赛克,不够清晰,为了调高清晰度,图片越来越大。
### 小图片base64
在应用开发中有时会把一些图片转成Base64编码放在代码里,这会使数据量增大30%左右,所以这种方式不适合较大图片。而对于小图标来说,增加的绝对数据量并不大,却能减少一个http请求,也不失为一种优化方案。不过,组件库较普通应用对数据量更为敏感,这种方式不是上策。
### css sprite(雪碧图)
另一种处理小图标的经典方案是雪碧图(CSS Sprite),但这种基于精准位置信息的图标引用方式在移动端基于rem的布局中并不是那么受欢迎,因为rem布局自身就难以精确,如果用于组件库也会给按需引用带来一些不便。
对于小图标,在移动端更需要的是矢量方案,天然适配各种像素密度的屏幕。
## Icon Font方案
在组件库中,比较流行的是采用基于CSS3字体(@font-face)的ICON FONT方案,也就是把图标放在一个自定义字体文件中。有很多优点,比如:
ICON在字体中是矢量存在,受移动端欢迎
良好的浏览器兼容性,web字体并非CSS3发明,更早之前的浏览器(包括IE6)也都事实上支持,虽有些许差异,终归是有办法兼容的
可通过CSS控制ICON颜色和透明度等样式,甚至可以实现颜色渐变效果
## svg方案
我们并没有选择ICON FONT方案,我们认为SVG方案更适合移动端组件库:
SVG虽在PC端个别古董浏览器中兼容较差,但在移动端兼容良好
ICON FONT被认为是文本,所以一些浏览器会对其进行抗锯齿处理,这可能导致图标不那么锐利,清晰度打折扣
SVG样式控制比ICON FONT更灵活,甚至可以控制图标各个部分的颜色,实现彩色图标。而这对ICON FONT来说是不可能实现的
ICON FONT通常是用伪对象或伪类插入页面,其展示受到“line-height”、“vertical-align”、“letter-spacing”、“word-spacing”及字体相关CSS属性影响,也受到字体字符设计本身影响。而SVG在页面中就是一个标签,更方便控制,语义化也更好
结合symbol元素可以实现所谓“SVG Sprite”,也就是把很多SVG图标整合在一起,通过ID引用指定图标,可以复用。这种方式比CSS Sprite还要方便,因为不需要关心图标具体位置信息
![svg](https://box.kancloud.cn/944ec468367e1e8678b039ba58c159e7_448x482.png)
SVG Sprite也不是必须手动去组合,借助webpack的 svg-sprite-loader 可以轻松实现SVG Sprite的动态生成,图标的按需加载不是梦。
好了,限于篇幅,这次先聊这么多,更多内容请关注我们团队的公众账号“全栈探索”。