# 圖標
組件庫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 Sprite也不是必須手動去組合,借助webpack的 svg-sprite-loader 可以輕松實現SVG Sprite的動態生成,圖標的按需加載不是夢。
好了,限于篇幅,這次先聊這么多,更多內容請關注我們團隊的公眾賬號“全棧探索”。