本文翻譯自 How to Favicon in 2024: Six files that fit most needs
本文原作者 Andrey Sitnik 是 PostCSS 和 Autoprefixer 的作者,首席前端工程師,現居西班牙巴塞隆納。
是時候再想一下,要如何打造現代瀏覽器的 Favicon?終結圖示產生器的混亂。目前,前端開發者為了在瀏覽器分頁或觸控螢幕上,顯示小小的網站標誌,就得要處理 20 個以上靜態 PNG 檔案。更聰明的做法要怎麼進行?只要加上最少量的一組圖示,即可適用於大多數現代需求,請繼續看下去。
事實證明,Favicon 這個話題,比任何人所希望的還要難搞。因此,為了已經受盡折磨,還有清楚知道該做什麼事情的大家,整篇文章統整成只要 2 行的程式碼片段。然而,建議還是要發揮追究到底的精神!
作者的 2022 年註記: 新的一年到來,這篇文章也稍微修改,證明這裡的內容還是非常值得參考!
作者的 2023 年註記: 再次保證,這裡一定有最新的資訊!
作者的 2024 年註記: 已經確認過,所有內容都還是最新的!
極致簡短版
其實只要有 5 個圖示和 1 個 JSON 檔案即可,不需要放上好幾打圖示。
用在瀏覽器的 HTML:
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png"><!-- 180×180 -->
<link rel="manifest" href="/manifest.webmanifest">
還有用在 Web App 的 Manifest:
{
"icons": [
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
}
這樣就好了。如果想要知道這是怎麼歸納出來、得要妥協的決定,還有從無到有一步一步做出這一組,別轉台,都在這篇文章剩下的部分。
完整版,全部解釋一遍
達到完美的境界,並非不能再增加,而是無法再減少。
Antoine de Saint-ExupéryAirman’s Odyssey
Favicon,也就是 “Favorite Icon” 的縮寫,這個概念在 2000 年代左右就滿街跑了。大家都有看到瀏覽器分頁上可愛的小圖片,協助分辨已經打開的網站。使用者預期網站有 Favicon,這是會獲得其他人敬重的小事情之一。
即使是蘋果公司,一直跟 Cupertino 以外的圖示美學互看不順眼,長年在 Safari 佛系對待 Favicon,最終還是放棄。現在,已經在所有裝置上正確顯示。
如果是對外公開的網站,就必須要有 Favicon。讓人悲傷的是,使用者看到的圖示,背後有非常多個。
因此,為了所必要檔案,因為螢幕和裝置持續增加,這種混雜成一團的工作,很常就交給 Favicon 產生器工具來減輕負擔。只有神智不清的人,才會想要花費好幾小時手動來做。畢竟,我們是來做網站的,而不是讓瀏覽器廠商開心。
身為 NanoID 的作者,以及極簡開源支持者,我傾向以稍稍不同的方向思考。最有效率的一組網站圖示有哪些?哪些格式已經過時?哪些圖示種類能夠以小小的妥協取代?
因此,我著手打造最精簡的 Favicon 列表,可以在所有場合,以及所有瀏覽器使用。但是,會捨棄一些極端情況。即使如此,還是行得通,就只是沒有 100% 完美。
終極版 Favicon 設定
與其做一堆不同尺寸的圖片,我決定倚賴 SVG 與瀏覽器的向下相容。如果擔心效能,這裡直接說明:
- 瀏覽器在背景下載 Favicon,所以大一點的 Favicon 圖片不會影響網站效能
- 在沒有必須要用到點陣圖的時候,非常適合以 SVG 減少圖片檔案大小。對於大多數的標誌來說,最終檔案會遠比 PNG 還要小。
- 這組極簡版就只有 3 個 PNG 圖片,可以使用進階工具來把檔案大小最佳化。這解決了沒有上網吃到飽方案網路使用者的問題。
現在,要進一步揭露經過研究和實做想出來的極簡圖示組。這份清單應該可用於所有常見的瀏覽器與裝置,新或舊的皆可。
I. 過時瀏覽器使用的 favicon.ico
其實,ICO 檔案格式有資料夾結構,可以把不同解析度的檔案打包起來。建議只要用單一的 32x32 圖片,除非手上的檔案無法良好地降為 16x16(例如:會變得模糊)。遇到這種情況,可以向設計師要求出個專為小像素網格的特別版本標誌。
資料夾、靜態檔案資料夾結構和快取破壞方面就不要自作聰明。https://example.com
這個網站的 Favicon 就要放在 https://example.com/favicon.ico
。像是 RSS 閱讀器等工具,只會找伺服器的 /favicon.ico
,絕對不有其它地方。
連至 .ico 的 <link>
要有 sizes="any"
,這是為了修正 Chrome 的 Bug,會選擇 ICO 檔案,而不是 SVG 檔案。
II. 現代瀏覽器能以單獨的 SVG 圖示擁有亮色/暗色版本
SVG 是一種描述曲線的向量格式,而不是像素。尺寸很大的時候,效能比點陣圖片還要好。撰寫這篇文章的時候,72% 的瀏覽器支援 SVG 圖示。
HTML 頁面必須要在 <head>
裡面有rel="icon"
、type="image/svg+xml"
和href
包含連至 SVG 檔案等屬性的 <link>
標籤。
SVG 能夠加上描述 CSS 用的 <style>
標籤,是一種 XML 格式。既然可以放任何 CSS,也就能用 @media (prefers-color-scheme: dark)
這樣子的 media query。達成在亮色與暗色系統主題之間,以同個圖示切換。
III. 蘋果裝置使用的 180×180 PNG 圖片
蘋果裝置上,如果在 iPhone 或 iPad 主畫面新增網頁捷徑,會使用的圖片,稱為蘋果觸控圖示。HTML 頁面要在 <head>
裡面加入 <link rel="apple-touch-icon" href="apple-touch-icon.png">
。
從 iOS 8 開始,在 iPad 得使用 180x180 解析度的圖片,其它裝置會降級。但是,如果來源檔案的品質夠高,降級不會對終端使用者造成傷害(稍後會回頭來談這件事)。
小附註:在蘋果觸控圖示的內緣周圍設下 20 像素
留白,然後加上一些背景顏色,會比較好看。任何一款圖片編輯器都可以做到。
IV. Android 裝置使用的 Android Web 應用程式 Manifest,192x192 和 512x512 PNG 圖示
- Web 應用程式 Manifest 是 JSON 檔案,裡面有讓瀏覽器把網站安裝成系統應用程式的所有細節。這個格式誕生於 Google 倡議的 PWA。
- HTML 頁面必須要有 標籤,連至 Manifest 檔案。
- Manifest 要有
icon
欄位,連至 2 個圖示:192x192 是在主畫面顯示的,512x512 是 PWA 在讀取時當作進場等待畫面。
{
"icons": [
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
}
有遺漏的嗎?
當然,市面上還有更多 Favicon 的配方,有些非常冷門。接著,來看看這份設定怎麼應對。或許,是時候向沒那麼成功的格式說再見了。
Windows Tile Icon
微軟 Edge 曾經支援的特殊圖示格式,能把網站釘選在開始選單。近期版本的 Windows 已經不是必備。
Safari Pinned Icon
先前,Safari 要求釘選分頁得有黑白 SVG 圖示。不過,Safari 12 開始,釘選頁籤可以用一般 Favicon 就好。甚至 apple.com 都不再用 mask-icon
。
rel="shortcut"
很多教學(已經過時的)提到在 HTML 加入這樣的 favicon.ico
:
<link rel="shortcut icon" href="/favicon.ico" sizes="32x32">
請注意,shortcut
從來就不是有效的連結關係。請拜讀這篇 Mathias Bynens 10 年前的好文,說明一開始就沒必要用 shortcut,只要 rel="icon"
就夠了。
Opera Coast
從前,iOS 有一款實驗性質的瀏覽器叫做 Opera Coast,要用特殊的 228x228 圖示。此瀏覽器在 2017 年離開 App Store,令人懷疑是否能在多次 iOS 更新存活下來。
現在,向殞落的戰士們揮手說再見後,來看看為了仍挺立的那群,而打造終極的 Favicon 組合。
打造終極 Favicon 組合
以下是 6 個步驟打造終極簡Favicon 組合。只要有預計當作標誌的 SVG 檔案,就可以開始。
步驟 1:準備 SVG
SVG 圖片必須是正方形。在系統打開原始檔案,檢查圖片的寬和高。調整 SVG 尺寸很簡單,任何 SVG 編輯器皆可。如果是用 Inkscape 來更改文件尺寸,選擇 File → Document Properties,接著使用 Object → Align and Distribute 把標誌置中。
把檔案儲存為 icon.svg。然後,把 SVG 稍做修改,讓它可以在現代系統主題好好表現。向設計師詢問在暗色主題的顏色要如何反轉(黑白的標誌就只要把黑色改為白色。)
現在,在文字編輯器打開 SVG 檔案。尋找暗色或沒有 fill
的 <path>
。加入會因為主題改變的 CSS Media Query,把 fill
改成想要的顏色。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
+ <style>
+ @media (prefers-color-scheme: dark) {
+ .a { fill: #f0f0f0 }
+ }
+ </style>
- <path fill="#0f0f0f" d="…" />
+ <path class="a" fill="#0f0f0f" d="…" />
</svg>
這裡 SVG 的 Media Query 技巧,也可以用在把 Favicon 加上廣色域 P3 顏色。
步驟 2:加上 ICO 檔案
在點陣圖編輯器打開 icon.svg
檔案。推薦使用 GIMP,免費而且跨平台。
把 SVG 改為點陣輸出。設定寬和高都 32 像素。存成名為 favicon.ico
的檔案,32 位元/像素、8 位元 Alpha,沒有色票設定。
如果沒有在用 GIMP,也可以安裝 Inkscape 和 ImageMagick,在終端機把 SVG 轉成 ICO:
inkscape ./icon.svg --export-width=32 --export-filename="./tmp.png"
# 在 Windows,下指令 `magick convert ./tmp.png ./favicon.ico`
convert ./tmp.png ./favicon.ico
rm ./tmp.png
把圖片縮為 16x16,檢查還夠不夠清楚。如果已經太模糊,最好向設計師要客製迷你版的標誌。
額外加入 16x16 版本的圖示:
打開 32x32 的
favicon.ico
圖示。新增 16x16 尺寸的圖層。
把 16x16 版本的圖示放進圖層。
輸出檔案。GIMP 會把每個版面都存成不同版本的圖示。
或者用 ImageMagick 也可以:
convert ./icon-32.png ./icon-16.png ./favicon.ico
步驟 3:建立 PNG 圖片
再次用點陣圖編輯器打開原始 SVG 檔案,建立 512x512 的圖片。輸出為 icon-512.png
。
把圖片縮成 192x192,輸出為 icon-192.png
。把這個檔案再縮成 140x140,畫布設定成 180x180,輸出為 apple-touch-icon.png
。
或者,在 Inkscape 這樣做:
inkscape --export-type="png" --export-width=512 --export-filename="./icon-512.png" ./icon.svg
inkscape --export-type="png" --export-width=192 --export-filename="./icon-192.png" ./icon.svg
步驟 4:將 PNG 和 SVG 檔案最佳化
最優秀的 SVG 最佳化工具是 SVGO,執行指令:
npx svgo --multipass icon.svg
Squoosh 是很好用的點陣圖最佳化網路應用程式:
- 在 Squoosh 打開
icon-512.png
。 - 把壓縮設定改成
OxiPNG
。 - 開啟 "Reduce palette"。
- 設定為 64 個顏色。
- 移動滑桿,比較前後差別。如果有察覺到,就增加顏色。
- 儲存檔案。
icon-192.png
和 apple-touch-icon.png
也一樣用這些步驟。
步驟 5:把圖示加入 HTML
必須要把連至 favicon.ico
和 apple-touch-icon.png
的連結加入 HTML。
靜態 HTML:
<title>My website</title>
+ <link rel="icon" href="/favicon.ico" sizes="32x32">
+ <link rel="icon" href="/icon.svg" type="image/svg+xml">
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png">
不過,建議用打包工具產生快取破壞 (名稱帶有檔案的 Hash,當作是 Fingerprint)。如果是在 Webpack,使用 HtmlWebpackPlugin
:
- 建立 index.html 範本。
- 把範本加入外掛選項:
new HtmlWebpackPlugin({ template: "./view/index.html" });
- 定義帶有連結的 HTML 範本(這裡的範例使用
HtmlWebpackPlugin
加入檔案,這可以是任何偏好的範本語言):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My website</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" type="image/svg+xml" href="<%=
require('./icon.svg').default
%>">
<link rel="apple-touch-icon" href="<%=
require('./apple-touch-icon.png').default
%>"
>
</head>
<body></body>
</html>
- 使用
copy-webpack-plugin
複製favicon.ico
,才不會在檔名加上 Hash。
附贈提示:建立 Staging 環境的額外圖示
Favicon 是用來分辨正式跟 Staging 環境的絕妙方法。我發現 Staging 使用不同圖示,用來避免任何造成得不償失的狀況非常好用。
用相同的標誌建立 favicon-dev.ico
,但是把顏色反轉(或是任何覺得有道理的方法)。SVG 也這樣做,新增 icon-dev.svg
。
接著,在 HTML 範本,以 process.env.NODE_ENV === 'production'
條件取代圖示:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My website</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
- <link rel="icon" href="/favicon.ico" sizes="32x32">
+ <link rel="icon" sizes="any" href="<%=
+ process.env.NODE_ENV === 'production'
+ ? '/favicon.ico'
+ : require('./favicon-dev.ico').default
+ %>">
<link rel="icon" type="image/svg+xml" href="<%=
- require('./icon.svg').default
+ process.env.NODE_ENV === 'production'
+ ? require('./icon.svg').default
+ : require('./icon-dev.svg').default
%>">
<link rel="apple-touch-icon" href="<%=
require('./apple-touch-icon.png').default
%>">
</head>
<body></body>
</html>
步驟 6:加入網路應用程式 Manifest
如果是靜態 HTML,新增檔名是 manifest.webmanifest
的 JSON 檔案:
{
"name": "My website",
"icons": [
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
}
在 HTML 裡連結過去:
<title>My website</title>
+ <link rel="manifest" href="/manifest.webmanifest">
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
在 Webpack,可以使用 webpack-pwa-manifest 外掛:
plugins: [
// …,
new WebpackPwaManifest({
name: 'My website',
icons: [
{ src: resolve('./icon-192.png'), sizes: '192x192' },
{ src: resolve('./icon-512.png'), sizes: '512x512' }
]
})
]
感謝閱讀!如你/妳所見,以現代網頁技術,打造終極 Favicon 組合得要做的事情,變得相當直覺。即使照著這些步驟來做,並不會花費多少時間,有自動化工具達到一樣的效果,會讓事情變得更讚!如果有意願打造出來,歡迎隨時在 Twitter 上找我。如果可以幫上忙,會非常榮幸!
原文版權所有:Andrey Sitnik
翻譯版權所有:@ymcheung