黑化你的 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

简单地讲就是浏览器标签页或收藏夹里显示的这些图标。
notion image
具体概念我们直接看维基百科就好:
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 主要有这几个“麻烦”:
  1. 它会在页面加载完成后最后加载,而在 <head> 中声明则会首先加载;
  1. 若多站点共用一个根目录,则同一个 favicon.ico 可能难以满足个性化需要,有时甚至需要不同页面显示不同 favicon;
  1. 最后,越来越丰富的应用需要更多不同规格和设计的 icon 满足各种场景。
    1. 比如 iOS 的 Safari 浏览器有一个很实用的添加到主屏幕功能(Android Chrome 或新 Edge 也有),如果不正确声明 icon,就无法生成合理的桌面图标。下图左边两个就是未正确配置的结果。
      notion image
所以,在<head>中声明 icon 变得极为必要。favicon 也不再局限于 .ico 格式,可以是 .png,.svg 甚至 .gif 等。

如何声明

完整的 favicon 系统需要众多规格尺寸的文件,感兴趣的同学可以直接看这里。(实际上这个链接里的网站可以帮你一键生成几乎所有的 favicon)
但实践中我们似乎并无必要配置如此众多的 favicon,这里挑几个比较常见的供参考:
吐槽下 Safari 蛋疼的缓存机制,给调试 mask-icon 增加不少麻烦。
Apple 对 pinned tab icon 有诸多限制,比如要求单图层,viewBox "0 0 16 16" 等,但不严格遵守这些限制似乎也可以正常使用,个人没有深入研究。
notion image
更多关于 favicon 的内容我就不敢讲了,感兴趣的请看这些介绍:

进入正题 - 黑化

两种方法,推荐更加灵活的 JS 法。

修改 .svg 样式

首先你的 favicon 必须是 .svg 格式,不然无从谈起,你可以通过 Adobe Illustrator 或一些在线转换服务获得这样的文件。你的声明看起来可以是这样:
接着只要修改这个 .svg 文件,在它的 <style> 中添加 prefers-color-scheme: dark 属性即可。浏览器会自动根据系统设置调用对应样式。
完整的 .svg 差不多是这样:
这个方法本身并不复杂,但实际使用中的两个主要限制是:
  1. 只能使用 .svg 格式的图标;
  1. 无法实时刷新。黑暗和亮色切换后,必须刷新页面才能看到效果,暂不清楚不同浏览器缓存对此有多大影响。
普通访问者如果不特意测试,应该不会感知到“无法实时刷新”,但自己知道就很难受。
所以就有了另一种”实时“的方法

通过 JS 控制

这也是 Github 使用的方法。通过 JS 替换声明中 href 路径。
假设你的声明如下:
请准备亮色和黑暗两种 favicon。JS 代码如下:
addListener 这个参数已经过时,这里已经改为最新的addEventListener,在 body 中引入以上 JS 即可。
这里有个坑需要注意,如果你同时声明了其它 link rel="icon",比如 16x16 的那个,请在声明中将尺寸为 32x32 的放在最前,否则浏览器调用的是 32x32 的 icon,而 JS 脚本修改的将是它读到的第一个 link rel="icon" 声明。
好了,现在你拥有一个可以实时切换黑暗模式的 favicon 了。
notion image

Have fun!

 
💡
This article is licensed under CC BY-NC-SA 4.0. All rights to the work belong to the author. For commercial use, please contact the author for permission. For non-commercial use, please provide attribution to the source.
Author: Dukewill Source: blog.daisea.com
 
 

© Dukewill 1989 - 2024