圖標是頁面中很是友好的附加物,許多網站都會使用各類圖標來美化頁面樣式,給用戶提供更好的指引。本文將會和你們一塊兒學習頁面圖標的發展史,以及當前的最優解決方案。css
編寫圖標最簡單的方式就是使用一張圖片,如:html
<html> <body> 圖標 <img src="xxx.png" /> </body> </html>
我在剛開始寫頁面的時候就是這樣作的,感受 so easy,直到業務變得愈來愈複雜,我就不得不思考如下幾個問題:瀏覽器
對於適配多個客戶端的問題,設計師們一般都會給咱們提供多個尺寸的設計圖(@1x 圖、@2x 圖),因而咱們就能夠根據不一樣的客戶端來選擇對應尺寸的圖片。緩存
一般使用方式是:媒體類型 或者 配置 srcset 。dom
例如:svg
<html> <head> <style> /* 使用媒體查詢,爲每一個端適配不一樣尺寸的圖片 */ .@media screen and (max-width: 300px) { .img { background-image: url("1x.png"); } } .@media screen and (max-width: 600px) { .img { background-image: url("2x.png"); } } </style> </head> <body> <!-- srcset 可讓不一樣的客戶端自動匹配合適尺寸的圖片--> <!-- 如:當設備像素比爲 2 時,瀏覽器會自動選擇 2x 圖進行渲染--> <img src="1x.png" srcset="1x.png 1x, 2x.png 2x" /> </body> </html>
經過上面的方法,多客戶端適配問題解決了,但咱們使用了多張內容相同、尺寸不一樣的圖標,這無疑增長了圖片的數量。工具
隨着圖片的增多,圖片管理就是一個問題。每一張圖片都會發起一個 HTTP 請求,而瀏覽器並行加載同一域名下的請求是有限制的,太多的圖片沒法所有並行加載,就會進行排隊加載,排在後面的圖片也就不能及時獲得渲染。佈局
一般,解決大量圖片 HTTP 請求,有如下兩種方式:學習
雪碧圖指的是,將全部小圖片合併成一張大圖片。在瀏覽器渲染時,這張大圖片只須要發起一次 HTTP 請求,而後就被瀏覽器緩存起來了,當再次使用該圖片時,就會直接從緩存中進行讀取,從而避免了發起屢次 HTTP 請求。字體
首先,咱們須要將許多小圖片合成一張大圖:
而後在 CSS 中進行定位。
.icon1, .icon2, .icon3, .icon4 { width: 54px; height: 54px; background: url("../大圖.png"); } /* 定位背景圖,讓圖片顯示到對應的位置 */ .icon1 { background-position: -168px 0px; } .icon2 { background-position: -56px 0px; } .icon3 { background-position: 0px 0px; } .icon4 { background-position: -112px 0px; }
能夠看到,使用雪碧圖佈局時,全部的圖片都使用了同一張大圖,而後使用背景圖去定位,以區分不一樣的小圖標。
總結一下雪碧圖的特色:
接下來,咱們看一下 Base64 圖:
Base64 圖指的是,將一張圖片數據編碼成一串字符串,並使用該字符串代替圖像地址。
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAYAAABIdFAMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHhJREFUeNo8zjsOxCAMBFB/KEAUFFR0Cbng3nQPw68ArZdAlOZppPFIBhH5EAB8b+Tlt9MY" />
能夠看到,圖片的 src 並非一個地址,而是一個字符串,這樣甚至能夠不發起 HTTP 請求,就能渲染圖片。
Base64 的原理是
Data URLs,即:前綴爲
data:
協議的 URL,容許開發者向 HTML 中嵌入小文件。
總結一下 Base64 圖的特色:
Ok,咱們來總結一下傳統圖片渲染圖標的幾種方式:
最後剩下動態修改圖片顏色的問題,這個就比較難控制了,能夠用 CSS Filter 去作濾鏡,經過調整圖片的模糊度、對比度、灰度、透明度等,間接地改變圖片顏色。
例如:
img { // 讓圖片變灰 filter: grayscale(100%); // 讓圖片變模糊 filter: blur(5px); // ... }
可是 CSS Filter 能修改的顏色是有限的,若是想任意修改圖標顏色,咱們繼續往下看。
隨着互聯網的不斷髮展,字體圖標逐漸來到了咱們的視野,它能夠像處理文字同樣去處理圖標,大大地提升了圖標的靈活性。使用字體圖標能夠很是輕鬆地修改圖標顏色。
字體圖標使用很是方便,咱們只須要在頁面中引入對應的字體文件,而後編寫對應的字符就能夠了。
字體圖標有兩種寫法:
例如:
<html> <head> <style> /* 首先引入字體文件 */ @font-face { font-family: "iconfont"; src: url("iconfont.eot"), url("iconfont.woff") format("woff"), url("iconfont.ttf") format("truetype"), url("iconfont.svg#iconfont") format("svg"); } /* 定義字體類 */ .iconfont { font-family: "iconfont"; font-size: 16px; } /* 在僞類中編寫 unicode 字符 */ .icon-edit:before { content: "\e603"; } </style> </head> <body> <!-- 使用 &# + unicode 編碼能夠渲染對應的字符。 --> 直接使用字符編碼: <i class="iconfont"></i> 使用類名渲染(將字符寫在了僞類中):<i class="iconfont icon-edit" style="color:red" ></i> </body> </html>
能夠看到,有了字體圖標後,咱們能夠像處理文字同樣去修改圖標的顏色。
字體圖標的本質是一種字符,而字體是渲染字符的一種方式,它決定了咱們在鍵盤上敲打的字符最終在頁面上長什麼樣。
這就比如書法家寫字,不一樣的字體就是不一樣的書法家,不一樣的書法家雖然都在寫同一個字,可是因爲字跡的不一樣,寫出來的文字也就大不相同。
試想一下:有一個特立獨行的書法家,他並不按照常規的寫法來寫字,他寫出來的字都是一個個的小圖標,那不就是字體圖標了嗎 😄。
其實,書法家寫字這個道理,在網頁中也是同樣的。
頁面在渲染文字的時候,會先將文字轉換爲對應的 unicode 編碼,而後根據 css 中配置的 @font-face url
找到對應的字體文件(eot ttf woff 等),接下來在該字體文件中找到這個 unicode 編碼對應的繪製外形,最後繪製在頁面上。
咱們看到的內容 = fontFamily(unicode);
在計算機中,咱們能看到的全部字符,底層都是用二進制來表示的,如:空格符在二進制中就是 00100000
,大寫的字母 A
在二進制中就是 01000001
。
爲了方便維護字符和二進制的關係,前輩們將這些對應關係記錄成一張表,如:
ID | 字符 | 二進制 |
---|---|---|
32 | 空格符 | 00100000 |
65 | A | 01000001 |
這個表就是咱們常說的字符編碼,上表即 ASCII 編碼的一部分。
最初的 ASCII 編碼只能表示 128 個符號,主要存儲的是 26 個英文字母的大小寫和數字等。有了 ASCII 編碼後,咱們就能編寫對應的字體去渲染表中的字符了,但其餘沒有被記錄的符號也就沒法顯示了,如:不一樣國家的漢字、emoji 符號等。
爲了解決中文字符編碼問題,國家制定了 GB2312 編碼,該編碼收錄了 6763 個漢字,涵蓋了中國大陸 99.75% 的使用頻率,能知足絕大多數的漢字需求。
但 GB2312 編碼只適用於中文,而世界上還有 200 多個國家,他們也有本身獨特的文字,難道每個國家都須要自制一套字符編碼嗎?
其實不用,在 1991 年 10 月,誕生了 unicode 編碼,它制定了一套統一的編碼標準,收納了世界上全部國家的文字符號,到目前爲止,已經有 100 多萬個符號。
unicode 最多 4 個字節,一個字節 8 個比特位(表示二進制中的 0 或 1),也就是
2**32
個狀態,徹底能夠容納世界上全部的符號。
因此,任何一個符號,均可以在 unicode 編碼中被找到。
總結一下字體圖標的特色:
最後,字體圖標雖好,但它的本質仍然一種文字,因此 CSS 在設置 color 時只能選一種顏色,若是咱們想製做一個多色的小圖標,也就無能爲力了。
SVG 誕生於 1999 年,目的是用來繪製矢量圖形,它主要經過定義必要的線和形狀來建立一個圖形。
SVG 採用 XML 格式的語法來畫圖,例如:
<html> <head> <style> .my-style { /* 控制填充色 */ fill: red; } .my-style use { color: orange; } </style> </head> <body> <svg style="display: none;"> <symbol viewBox="0 0 24 24" id="heart"> <path d="M17,0c-1.9,0-3.7,0.8-5,2.1C10.7,0.8,8.9,0,7,0C3.1,0,0,3.1,0,7c0,6.4,10.9,15.4,11.4,15.8 c0.2,0.2,0.4,0.2,0.6,0.2s0.4-0.1,0.6-0.2C13.1,22.4,24,13.4,24,7C24,3.1,20.9,0,17,0z" ></path> </symbol> </svg> <svg class="my-style"> <use xlink:href="#heart" /> </svg> </body> </html>
能夠看到,首先咱們把須要使用的圖標封裝到 symbol 標籤中,在使用時只須要 use 一下就能夠了。這跟咱們定義一個 CSS class 而後再去 HTML 中引用是一個道理。
若是是用封裝好的 SVG 庫就更簡單了,SVG 庫會把全部用到的圖標封裝到一個 JS 文件中,咱們只須要引入這個 JS 文件,而後就能直接 use 對應的圖標了。
咱們再看一個多色 icon 的例子:
<html> <head> <style> /* svg 中的元素存在於 shadom 中,能夠經過自定義變量傳遞參數 */ .icon { width: 100px; height: 100px; margin-right: 10px; } .icon--fill { fill: grey; } .icon--color { fill: #ef5b49; --handle-color: #c13127; --cup-color: #ef5b49; --smoke-color: #cacaea; } .icon--color-alt { fill: #2f3fff; --handle-color: #1f2bac; --cup-color: #2f3fff; --smoke-color: #a5acbd; } </style> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" class="hidden"> <symbol id="icon-coffee" viewBox="0 0 20 20"> <title>icon-coffee</title> <!-- 使用自定義變量 --> <path fill="var(--handle-color)" d="M15,17H14V9h3a3,3,0,0,1,3,3h0A5,5,0,0,1,15,17Zm1-6v3.83A3,3,0,0,0,18,12a1,1,0,0,0-1-1Z" /> <rect fill="var(--cup-color)" x="1" y="7" width="15" height="12" rx="3" ry="3" /> <path fill="var(--smoke-color)" d="M7.07,5.42a5.45,5.45,0,0,1,0-4.85,1,1,0,0,1,1.79.89,3.44,3.44,0,0,0,0,3.06,1,1,0,0,1-1.79.89Z" /> <path fill="var(--smoke-color)" d="M3.07,5.42a5.45,5.45,0,0,1,0-4.85,1,1,0,0,1,1.79.89,3.44,3.44,0,0,0,0,3.06,1,1,0,1,1-1.79.89Z" /> <path fill="var(--smoke-color)" d="M11.07,5.42a5.45,5.45,0,0,1,0-4.85,1,1,0,0,1,1.79.89,3.44,3.44,0,0,0,0,3.06,1,1,0,1,1-1.79.89Z" /> </symbol> </svg> 使用 <svg class="icon icon--color" aria-hidden="true"> <use xlink:href="#icon-coffee" href="#icon-coffee" /> </svg> </body> </html>
能夠看到,SVG 和 HTML 同樣具備樹形結構,結構中的 path 都是圖形中的一個區域,這些區域能夠被 CSS 選擇器匹配到。當咱們匹配到對應的區域時,就能進行對應的顏色修改了,一張多色的 SVG 圖就作好了。案例
總結一下 SVG 圖標的特色:
本文介紹了 3 種小圖標的使用方式,這裏作一個簡單回顧。
整體來講,3 種圖標使用起來都很簡單,你們視狀況來定吧。