使用 SVG 輸出 Octicon

發表於2016-03-18

GitHub.com 現在不再使用字型來輸出圖示了。我們把程式碼庫中所有的 Octicon 替換成了 SVG 版本。雖然這些改動並不那麼明顯,但你馬上就能體會到 SVG 圖示的優點。

Octicon 上的對比
Octicon 上的對比

切換到 SVG 以後,圖示會作為圖片渲染而非文字,這使其在任何解析度下都能很好地在各種畫素值下顯示。可以比較一下左側放大後的字型版本和右側清晰的 SVG 版本。

為何使用 SVG?

圖示字型渲染問題

圖示字型從來只是一種 hack。我們之前使用一個自定義字型,並將圖示作為 Unicode 符號。這樣圖示字型就可以通過打包後的 CSS 來引入。只要簡單地在任意元素上新增一個 class,圖示就可以顯示出來。然後我們只使用 CSS 就能即時改變圖示的尺寸和顏色了。

不幸的是,雖然這些圖示是向量圖形,但在 1x 螢幕下的渲染效果並不理想。在基於 WebKit 的瀏覽器下,圖示可能會在某些視窗寬度下變得模糊。因為此時圖示是作為文字輸出的,本來用於提高文字可讀性的次畫素渲染技術反而使圖示看起來糟糕許多。

對頁面渲染的改進

因為我們直接將 SVG 注入 HTML(這也是我們選擇這種方式更大的原因),所以不再會出現圖示字型下載、快取、渲染過程中出現的樣式閃動。

頁面閃動頁面閃動

可訪問性

就像在《圖示字型已死》一文中所述,有些使用者會覆蓋掉 GitHub 的字型。對於患有讀寫障礙的使用者,某些特定字型是更加容易閱讀的。對於修改字型的使用者來說,我們基於字型的圖示就被渲染成了空白方框。這搞亂了 GitHub 頁面佈局,而且也不提供任何資訊。而不管字型覆蓋與否,SVG 都可以正常顯示。對於讀屏器使用者來說,SVG 能讓我們選擇是讀出 alt 屬性還是直接完全跳過。

圖形尺寸更合適

我們目前對每個圖示在所有尺寸下提供單一的圖形。因為站點的載入依賴了圖示字型的下載,我們曾被迫把圖示集限制在最重要的 16px 尺寸下。這讓每個符號在視覺上做出一些讓步,因為我們是針對 16px 方格進行優化的。當在新頁面或營銷頁上縮放這些圖示時,顯示的還是 16px 的版本。而 SVG 可以方便地 fork 全部的圖示集,在我們指定的每個尺寸提供更合適的圖形。當然對圖示字型也可以這麼做,但這樣使用者需要下載兩倍的資料量,可能更多。

便於創作

打包自定義字型是複雜的。一些 web 應用因此而生,我們內部也自己搞了一個。而用 SVG 的話,新增一個新圖示會變得像把一個 SVG 檔案拖入一個目錄這樣輕而易舉。

可新增動畫效果

並非一定要加動畫,而是有了新增動畫的可能性。而且 SVG 動畫也的確在例如預載入動畫等地方有實際應用。

如何實現

Octicon 在整個 GitHub 的程式碼庫中出現了約 2500 次。在用 SVG 之前,我們簡單地用 <span></span> 這樣簡單的標籤來引入。要切換到 SVG,我們先給新增了一個用來往 HTML 內直接注入 SVG 路徑的 Rails helper。我們先用這個 helper 讓員工測試了不同的 SVG 輸出方式,然後才對外發布。

Helper 的用法

輸入 <%= octicon(:symbol => "plus") %>

輸出

我們的方案

可以看見,我們最終上線的方案是往頁面 HTML 中直接注入 SVG。這樣就可以靈活地實時調整 CSS 的 fill: 宣告來修改顏色。

我們現在有一個 SVG 圖形的目錄而不是一個圖示字型,我們通過挑選,將裡面這些符號的路徑用 helper 直接注入到 HTML 裡。比如,通過 <%= octicon(:symbol => "alert") %> 來呼叫 helper 就可以的到一個警告圖示。Helper 會查詢同名的檔名,並且注入 SVG。

我們嘗試過好幾種在頁面中新增 SVG 圖示的方法,其中有些由於受到 GitHub 生產環境的限制而失敗了。

  1. 外部 .svg 檔案——最開始我們嘗試提供一個單一的外部“SVG 倉庫”,然後用 <use> 元素來引入 SVG 拼圖中的單個圖形。在我們當前的跨域安全策略和資源管道條件下,提供在外部提供 SVG 拼圖很難做到。
  2. SVG 背景——這種方式無法實時調整圖示的顏色。
  3. 用 <img> 與 src 屬性來引入 SVG——這種方式無法實時調整圖示的顏色。
  4. 將“SVG 倉庫”整個嵌入到每個檢視,然後使用 <use> ——把每個 SVG 都嵌入到整個 GitHub.com 的每個單頁想想就不對,特別是有時候這個頁面一個圖示都沒用到。

效能

在切換到 SVG 以後,我們還沒發現頁面載入和效能上有任何不良影響。我們之前曾預計渲染時間會大幅下降,但往往效能和人的感知更相關。由於 SVG 圖示被渲染為了指定寬高的影象,頁面也不再會像之前那樣閃動了。

同時由於我們不再輸出字型相關的 CSS,我們還能幹掉一些多餘的 CSS 程式碼

缺點和坑

  • Firefox 對 SVG 仍然有畫素值計算的問題,雖然圖示字型也有相同的問題。
  • 如果你需要 SVG 有背景色,你可能需要在外面包一層額外的 div。
  • 由於 SVG 是作為圖片提供的,某些 CSS 的覆蓋問題也需要重新考量。如果你看到我們的頁面佈局有任何奇怪的地方,請告知。
  • IE 瀏覽器下,需要對 svg 元素指定寬高屬性,才能正常顯示大小。
  • 在技術方案升級過程中,我們層同時輸出 SVG 和圖示字型。在我們仍然為每個 SVG 圖示指定 font-family 時會導致 IE 崩潰。在完全轉用 SVG 以後,這個問題就解決了。

總結

通過換掉圖示字型,我們能更方便、更快速、更有可訪問性地提供圖示了。而且它們看起來也更棒了。享受吧。

相關文章