SVG Favicon:支持情况、暗色模式与后备方案
SVG favicon 是用 type 为 image/svg+xml 的 link 标签引用的矢量图标,因此一个文件就能在任意尺寸下锐利渲染,而不是每个尺寸一张 PNG。因为它是一个文档,它可以携带一条 prefers-color-scheme 媒体查询,在暗色模式下把自己画成不同的样子。支持并非普遍:当前的 Chrome、Edge 和 Firefox 会渲染它,而 Safari 不用它作为标签页图标,所以要在它旁边保留一个 PNG 或 ICO 后备。
一个文件,而非一整套
光栅 favicon 是在导出时就做好的尺寸决定。SVG 则不是:浏览器会按每个位置所需的尺寸把它光栅化,所以 16 像素的标签页和 32 像素的书签栏能从同一个文件得到同样锐利的结果,而这个文件通常还比单张 PNG 更小。
问题在于支持并不均衡,而且 SVG favicon 并不能替代其余的图标集。Android 和 iOS 上的已安装应用位置仍然需要 PNG,Safari 的标签页图标也仍然需要走光栅路径。把 SVG 当作叠加在一套可用的 PNG 和 ICO 配置之上的升级项。
SVG favicon 在哪里可用
| 位置 | 行为 |
|---|---|
| Chrome / Edge tab | 渲染 SVG |
| Firefox tab | 渲染 SVG |
| Safari tab | 不使用它;回退到你的 PNG 或 ICO |
| iOS Home Screen | 使用 apple-touch-icon PNG,从不使用 SVG |
| Android / PWA install | 使用 web app manifest 中的 PNG |
head 标签
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/manifest.json">理解 image/svg+xml 的浏览器会选 SVG;其余的则回退到 ICO。无需做 user-agent 嗅探。
一个跟随暗色模式的 favicon
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<style>
path { fill: #111111 }
@media (prefers-color-scheme: dark) {
path { fill: #ffffff }
}
</style>
<path d="M20 80 L50 20 L80 80 Z" />
</svg>样式必须写在 SVG 内部。favicon 不会加载外部样式表。支持 SVG favicon 的浏览器一般都会顾及这一点;不支持的则直接使用光栅后备。
SVG favicon 常见问题
SVG favicon 能替代 favicon.ico 吗?
不能完全替代。任何按路径请求 /favicon.ico 的东西(以及任何不渲染 SVG favicon 的东西)都需要那个光栅文件。SVG 是补充,而不是替代。
为什么我的 SVG favicon 在 Safari 里不出现?
在撰写本文时,Safari 不把 SVG 用于标签页图标。它会回退到你声明的任何光栅图标,所以解决办法是确保那个后备存在且看起来正确。
rel="mask-icon" 是同一回事吗?
不是。mask-icon 是 Safari 的一个独立特性,它取一张扁平的单色 SVG 并为固定标签页着色。它会忽略你文件里的颜色,也不影响普通的标签页图标。