黑化你的 favicon - 打造完美站点图标
date
Dec 26, 2020
slug
darken-your-perfect-favicon
status
Published
tags
dark mode
favicon
mask-icon
站点图标
黑暗模式
summary
自黑暗模式(dark mode)流行以来,各个移动 APP 趋之若鹜,个人博客等网站也纷纷加入黑化大军。但留意下就会发现,鲜有博客让自己的 favicon 也适配了黑暗模式,部分黑色背景图标在黑暗模式下格外突兀。
type
Post
自黑暗模式(dark mode)流行以来,各个移动 APP 趋之若鹜,个人博客等网站也纷纷加入黑化大军。但留意下就会发现,鲜有博客让自己的
favicon
也适配了黑暗模式,部分黑色背景图标在黑暗模式下格外突兀。favicon 虽小,却是所有浏览器随时都会顶在头上的名片,黑乎乎一坨显示在那里实在有失身份(如果你的 favicon 颜色鲜明自然不会有这个问题)。在注意到 GitHub 的 favicon 适配黑暗模式后,我的好奇心再次被勾起 - 研究一番后发现 favicon 也是个深坑,而且中文内容稀少。这里只能进行简单梳理。
什么是 favicon
简单地讲就是浏览器标签页或收藏夹里显示的这些图标。

具体概念我们直接看维基百科就好:
Favicon 是 favorites icon 的缩写,亦被称为 website icon(网页图标),page icon(页面图标)或 urlicon(URL 图标)。Favicon 是与某个网站或网页相关联的图标。网站设计者可以多种方式创建这种图标,而目前也有很多网页浏览器支持此功能。浏览器可以将 favicon 显示于浏览器的地址栏中,也可置于书签列表的网站名前,还可以放在标签式浏览界面中的页标题前。
怎样设置
兼容性最好的方法是直接在站点根目录(root)下放置一个
favicon.ico
文件 - 这个很多人都知道,很多人不知道的是,这个 icon 文件甚至不需要是 .ico 格式,只要命名为 favicon.ico 即可。主流浏览器(IE ==!)在发现没有声明
link rel="icon"
时便会从根目录搜索 favicon.ico,所以请在根目录放上这样一个文件。这样就够了?
这样已经可以满足“显示站点图标”这一最简单的需求,而且无需额外配置,但如果仅仅这样的话,也没有写这篇文章的必要了。仅仅在根目录放置 favicon.ico 主要有这几个“麻烦”:
- 它会在页面加载完成后最后加载,而在
<head>
中声明则会首先加载;
- 若多站点共用一个根目录,则同一个 favicon.ico 可能难以满足个性化需要,有时甚至需要不同页面显示不同 favicon;
- 最后,越来越丰富的应用需要更多不同规格和设计的 icon 满足各种场景。
比如 iOS 的 Safari 浏览器有一个很实用的
添加到主屏幕
功能(Android Chrome 或新 Edge 也有),如果不正确声明 icon,就无法生成合理的桌面图标。下图左边两个就是未正确配置的结果。
所以,在
<head>
中声明 icon 变得极为必要。favicon 也不再局限于 .ico 格式,可以是 .png,.svg 甚至 .gif 等。如何声明
完整的 favicon 系统需要众多规格尺寸的文件,感兴趣的同学可以直接看这里。(实际上这个链接里的网站可以帮你一键生成几乎所有的 favicon)
但实践中我们似乎并无必要配置如此众多的 favicon,这里挑几个比较常见的供参考:
吐槽下 Safari 蛋疼的缓存机制,给调试 mask-icon 增加不少麻烦。
Apple 对
pinned tab icon
有诸多限制,比如要求单图层,viewBox "0 0 16 16" 等,但不严格遵守这些限制似乎也可以正常使用,个人没有深入研究。
更多关于 favicon 的内容我就不敢讲了,感兴趣的请看这些介绍:
- favicon-cheat-sheet by audreyfeldroy
进入正题 - 黑化
两种方法,推荐更加灵活的 JS 法。
修改 .svg 样式
接着只要修改这个 .svg 文件,在它的
<style>
中添加 prefers-color-scheme: dark
属性即可。浏览器会自动根据系统设置调用对应样式。完整的 .svg 差不多是这样:
这个方法本身并不复杂,但实际使用中的两个主要限制是:
- 只能使用 .svg 格式的图标;
- 无法实时刷新。黑暗和亮色切换后,必须刷新页面才能看到效果,暂不清楚不同浏览器缓存对此有多大影响。
普通访问者如果不特意测试,应该不会感知到“无法实时刷新”,但自己知道就很难受。
所以就有了另一种”实时“的方法
通过 JS 控制
这也是 Github 使用的方法。通过 JS 替换声明中
href
路径。假设你的声明如下:
请准备亮色和黑暗两种 favicon。JS 代码如下:
addListener
这个参数已经过时,这里已经改为最新的addEventListener
,在 body 中引入以上 JS 即可。这里有个坑需要注意,如果你同时声明了其它
link rel="icon"
,比如 16x16
的那个,请在声明中将尺寸为 32x32
的放在最前,否则浏览器调用的是 32x32 的 icon,而 JS 脚本修改的将是它读到的第一个 link rel="icon" 声明。好了,现在你拥有一个可以实时切换黑暗模式的 favicon 了。

Have fun!
本文采用 CC BY-NC-SA 4.0 许可协议,著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
作者:Dukewill
来源:blog.daisea.com