2023-12-06
如何讓使用 CDN 的 Tailwind CSS 也能在 VS Code 啟用 Tailwind CSS Intellisense 套件
HTML/CSS
2015.09.07
很久沒寫文章了,今天想跟大家分享 CSS sprite、Web icon font,以及 SVG sprite 這幾個東西的使用經驗。
這三個東西,雖然看似毫無關聯,但隱隱約約還是有種「進化」的感覺,如果你還在使用 CSS sprite 的技術,歡迎參考一下這篇文章,試著玩玩 Icon font 或 SVG sprite,瞭解並感受一下他們的特別之處吧 😄
當我們瞭解到每讀取一張圖,就會佔用一個 HTTP 需求時,我們改用 CSS sprite。
我們將所有網站會用到的 icon,全部集合起來放在同一張圖片裡,利用 class
再搭配 background-position
幫圖片做定位,就做到了 CSS sprite 的技術啦。
雖然可以有效減少 HTTP 需求,但他終究是圖片,只要把網站等比放大,圖片就可能會失真。在現今螢幕解析度提高,以及 RWD 網站盛行的環境下,用 CSS sprite 要面對的可能就是這種失真的小瑕疵。
另外一個比較惱人的困擾,就是要把所有的 icon 排在同一張圖片,再自己算出定位,其實很麻煩。雖然可以使用 compass 這樣的 CSS 預處理器幫忙,但也不是所有人都用 compass 啊 😊。
因為種種的因素,我們改用了另外一個技術:Web Icon Font (以下簡稱 icon font),我們利用一些字體文件,將文字轉成圖片。好處是解決了「失真」的困擾,因為即使放大縮小,它的本質還是文字,文字放大縮小是不會失真的,可以保持它原有的清晰度。
但困擾來了,正因為他是文字,所以必須乖乖遵守文字的規範,我們常碰到的問題就是在「鋸齒」與「抗拒齒」之間徘徊,通常瀏覽器都會替文字進行抗拒齒的優化,以免放大閱讀文字時,會有凹凸不平的鋸齒狀,有的時候,某些圖標我們需要這些鋸齒,但另外一些圖片我們需要抗鋸齒,線段類的圖案、圓弧狀的圖案 … 等等,會依照不同的樣式有不同的需求。
而且除了瀏覽器外,不同系統 (WIN, iOS)針對文字的抗拒齒演算法也不同,如果真的要錙銖必較的去調校,應該會調整的天荒地老。
當然,這篇文章不是要一味地告訴大家 Icon Font 的缺點,畢竟我自己也還在用 Icon Font XDD。
這種細微的的改變,一般肉眼看不太出來,而且在解析度較高的裝置觀看,這問題才會比較明顯。如果真的發生類似的問題,我們可以用 font-smooth
去調整:
/* 來源: https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth */ font-smooth: auto | never | always | <absolute-size> | length | initial | inherit -webkit-font-smoothing : none | subpixel-antialiased | antialiased
.icon { font-smooth: always; -webkit-font-smoothing: antialiased; }
但誠如 MDN 說的: this is non-standard and should not be used. (他們不是標準格式,不推薦使用在專案上)。
因此,如果真的有這類問題需要解決,我們可以改使用 SVG sprite。 Icon font 還有其他不方便的地方,例如受到 font-size
, line-height
.. 等等字型屬性的限制。一次要載入上百張 Icon font 的字型檔,但實際上用到的只是那幾張小圖,浪費了讀取的時間。最後還有一點是各家的 Icon font 整合不易.. 等。 當然還是有一些網站服務可以解決部分問題,所以這邊只是把會碰到的狀況列出來,就不再細談了。
在介紹 Icon font 文末提到有「網站服務」可解決部分問題,而這個網站也是我要介紹給大家的,就是 IcoMoon,他是一個整合眾家 Icon font 的網站,此外也支援 SVG 匯出。
該如何使用它?這邊不再贅述,我們只談 SVG sprite 的功能。
在講 SVG sprite 之前,還是先簡單講一下什麼是 SVG 吧 XDDD。其實對我而言,SVG 的定義很簡單,就是用程式碼畫圖,這句話傳達了兩個意思:一、你必須要寫程式碼;二、他是不會失真的向量圖。
透過以上範例,你會發現這張圖片所有的線段 (<path></path>
) 都是寫在 HTML 裡面,然後再利用 CSS 屬性去修改它的顏色、大小… 等樣式。
每一張圖片都有一個自己的 <path></path>
或者 <circle></circle>
… 這樣的屬性,通常會寫在網頁的最上方,再利用 <use xlink:href="#icon-video-camera"></use>
呼叫他。
雖然使用 SVG 可以有效解決解析度、鋸齒 … 等等這些問題,但參考我們上述語法,應該會發現,如果要載入多張不同的圖片,程式碼會拖得很長。為了解決這個問題,我們可以改用 SVG sprite,也就是將所有圖片存在 SVG 檔案,再從 HTML 呼叫他。
以 IcoMoon 網站為例,先選好你要的圖片,在匯出 SVG 之前勾選 Include Tiles (CSS Sprite)
解壓縮之後,找到 sprite/
目錄,裡面有一個 sprite.svg
,原理就跟 sprite.png 一樣,會把所有圖案排列整齊,差別在於它是向量圖,放大縮小都不會失真。
接下來只要在 HTML 載入這張 SVG 檔案,並且透過 ID
去呼叫對應的 icon 就可以了。
<svg class="icon" xmlns="http://www.w3.org/2000/svg"> <use xlink:href="sprite.svg#icon-facebook"></use> </svg> <svg class="icon" xmlns="http://www.w3.org/2000/svg"> <use xlink:href="sprite.svg#icon-feed"></use> </svg>
在 xlink:href
的地方,就輸入這個 svg 檔案的相對路徑,後面再寫 ID 即可,跟 CSS sprite 相比是不是簡單很多呢。我們不需要再寫 background-position
去調整他的位子,往後要新增其他的 icon,直接打開 sprite.svg 編輯就可以啦!
因為 svg 目前不支援絕對路徑,所以我沒辦法直接放在 codepen 讓大家看,因此另外做了一份頁面,請參考 🌍 範例網頁觀看效果,也歡迎使用 dev tools 玩玩看。
➡️ 範例:SVG sprite HTML demo
因為 IcoMoon 可以直接提供我們 SVG 的 path 程式碼,而且可以個別匯出,所以我用 IcoMoon 舉例。但如果你以後想用 IcoMoon 做 SVG sprite,請特別注意一件事情,就是你可能需要自行修改它的 SVG 檔案。
什麼意思呢?因為 IcoMoon 把 icon 的顏色、大小都寫死在 SVG 檔案裡,而且我覺得不是很好管理。
以 icon-facebook
為例,IcoMoon 是這樣寫的:
<svg id="icon-facebook" width="32" height="32" viewBox="0 0 32 32" x="48" y="0"> <path fill="#444444" d="M26.667 0h-21.334c-2.945 0-5.333 2.388-5.333 5.334v21.332c0 2.946 2.387 5.334 5.333 5.334h10.667v-14h-4v-4h4v-3c0-2.761 2.239-5 5-5h5v4h-5c-0.552 0-1 0.448-1 1v3h5.5l-1 4h-4.5v14h6.667c2.945 0 5.333-2.388 5.333-5.334v-21.332c0-2.946-2.387-5.334-5.333-5.334z"></path> </svg>
以下是我修改後的語法:
<svg> <symbol id="icon-facebook" viewBox="0 0 32 32"> <path d="M26.667 0h-21.334c-2.945 0-5.333 2.388-5.333 5.334v21.332c0 2.946 2.387 5.334 5.333 5.334h10.667v-14h-4v-4h4v-3c0-2.761 2.239-5 5-5h5v4h-5c-0.552 0-1 0.448-1 1v3h5.5l-1 4h-4.5v14h6.667c2.945 0 5.333-2.388 5.333-5.334v-21.332c0-2.946-2.387-5.334-5.333-5.334z"></path> </symbol> </svg>
你可以發現我改用 <symbol></symbol>
管理 icon,並且移除了他們固定的樣式。
如果不把 IcoMoon 寫的樣式移除,我們將無法用 CSS 控制這些樣式,所以請特別記住這一點!
我也有把 IcoMoon 跟我修改後的 SVG 檔案放到網站上,大家可以自行打開原始碼比對。
以上跟大家介紹 SVG sprite 的使用方法,以及該怎麼管理。希望對大家有所幫助囉
最近做了一个项目,把现有的iconfont项目转换成SVG,已经支持绝大部分github上流行的项目。希望可以帮助大家升级到SVG sprite的方案: http://leungwensen.github.io/svg-icon/