深色模式 Favicon:做一个能自适应的
一个深藏青色的标志会在深色标签页栏上消失。你可以用一个 SVG 解决,也可以用两个 PNG 解决,但你仍要在下面保留一个默认图标。
深色模式到底改变了什么
浏览器的标签页栏在浅色模式下是浅色的,在深色模式下是深色的。除非你让 favicon 跟着变,否则它不会变。一个在白色背景上很清晰的标志,在接近黑色的标签页上可能会消失,反过来,浅色标志在浅色浏览器界面上也是如此。
你有两种应对方式。发布一个会自己改变颜色的 SVG,或者发布两个 PNG 让浏览器根据系统设置来选择。SVG 方式是一个文件、一次请求。PNG 方式在更多客户端上有效,但它对按 media 切换 favicon 的支持并不一致,所以更多时候要依赖 fallback。
方法 A:一个自己翻转的 SVG
一个 SVG favicon 可以携带自己的 CSS。在 SVG 内部放入一个 prefers-color-scheme: dark 媒体查询,并在那里改变填充色。浏览器会读取系统设置,重新绘制图标,无需第二个文件,也无需额外的 link 标签。
这是首选方法。它只有一个文件,在任何尺寸下都保持清晰,而且是唯一一种用单个资源就能覆盖两种主题的方式。
带 fallback 的 SVG
<!-- In your <head>: SVG first, then the raster fallback -->
<link rel="icon" type="image/svg+xml" href="/icon.svg">
<link rel="icon" href="/favicon.ico" sizes="any">
<!-- icon.svg, with the theme rule baked in -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<style>
path { fill: #1a1a1a; }
@media (prefers-color-scheme: dark) {
path { fill: #f5f5f5; }
}
</style>
<path d="M6 6h20v20H6z" />
</svg>能读取 SVG 的浏览器会使用第一行并遵循媒体查询。其他一切都回退到 favicon.ico。
方法 B:两个带 media 作用域 link 标签的 PNG
如果你无法使用 SVG,就导出两个 PNG(比如一个深色标志配浅色背景的版本,和一个浅色标志配深色背景的版本),并在各自的 link 标签上用 media 属性做标记。浏览器会加载与当前主题匹配的那一个。
对此的支持参差不齐。有些浏览器会忽略图标链接上的 media 属性,只取它们能理解的第一个。这就是为什么最后一行很重要:一个没有 media 条件的普通 favicon.ico,是任何客户端都能回退到的默认值。
两个 PNG 的配置
<link rel="icon" type="image/png" href="/favicon-dark.png"
media="(prefers-color-scheme: dark)">
<link rel="icon" type="image/png" href="/favicon-light.png"
media="(prefers-color-scheme: light)">
<link rel="icon" href="/favicon.ico" sizes="any">把无条件的 favicon.ico 放在最后,这样即使浏览器忽略了 media 提示,也仍然有一个图标。
偷懒但确实管用的方式
如果这一切都不值得费力,那就用一个中间色调的标志。一种对比度足以在浅色和深色浏览器界面上都能看清的颜色(一种饱和的品牌色,既不接近黑色也不接近白色),用单个文件就能在两种主题下都清晰可读。
这是务实的默认做法。你失去了与每种主题的完美匹配,但换来一个永不消失的资源,也没有可能出错的 media 条件。
常见问题
如何让 favicon 在深色模式下改变?
使用带有 prefers-color-scheme: dark 媒体查询的 SVG favicon,在其样式中切换填充色,或者发布两个带 media 作用域 link 标签的 PNG。无论哪种方式,都保留一个普通的 favicon.ico 作为默认值。
深色模式 favicon 在每个浏览器中都有效吗?
带内部媒体查询的 SVG favicon 在现代浏览器上有良好支持。按 media 切换的 PNG favicon 可靠性较低,所以始终要包含一个无条件的 fallback 图标。
我能跳过深色模式,只用一个 favicon 吗?
可以。选择一个对比度足以在浅色和深色标签页上都能看清的中间色调标志。它只有一个文件,而且在任何一种主题下都不会消失。
favicon.ico 需要为深色模式而改变吗?
不需要。favicon.ico 是你为较旧客户端和爬虫准备的默认 fallback。让它保持为单一、可读的版本,用它上方的 SVG 或 PNG 链接来处理主题切换。