智能网页设计。第一部分:亮/暗模式图标。
如今,我们拥有了一项超酷的新功能,可以检测操作系统 UI 主题并根据主题更改网站视图。这让我们能够运用新技术编写可主题化且易于自定义的 CSS 和 HTML 代码。在本系列文章中,我将向您介绍如何为您的 Web 应用创建简单的可主题化设计。
虽然我们可以使用 CSS 和 HTML 更改页面的可视化效果,但有一个元素仍然不具备这种能力。你应该知道我在说什么了。没错,它就是网站图标 (favicon)。
如果你在黑暗模式下查看 Dev.to 或 Github 的图标,你会发现它们几乎看不见了。我们需要改变它,让图标在主题切换时做出反应。最合理的方法是使用media
link 元素的属性,它允许图标对传入属性值的 CSS 媒体查询做出反应。但遗憾的是,link 的 media 属性支持的媒体查询列表并不包含prefers-color-scheme
。
幸运的是,我们可以使用 JavaScript 来实现它。那就开始吧。
这是其工作原理的实时预览。
TL;DR对于那些想要现成解决方案的人,请使用该库:
rumkin / favicon-switcher
使图标对媒体查询做出反应
聆听主题切换
我们需要从页面头部收集所有链接元素,获取media
其属性并使用window.matchMedia()
方法进行匹配。此方法返回MediaQueryList,它允许监听更改,我们将使用它:
window.matchMedia('(prefers-color-scheme:light)').addListener((e) => {
e.matches // Determine wether query matched or unmatched
})
添加图标
现在我们需要在页面主体中插入不同主题的图标:
<link rel="icon" media="(prefers-color-scheme:dark)" href="favicon-dark.png" type="image/png" />
<link rel="icon" media="(prefers-color-scheme:light)" href="favicon-light.png" type="image/png" />
切换图标
要使浏览器切换标签页的图标,只需将元素设置为 中的<link>
最后一个元素即可。这可以正常工作,但 Chrome 目前存在一个 bug,在某些情况下会导致图标切换中断。为了避免此 bug,我们需要创建新的 元素并将其附加到 head 子元素列表中,放在其他链接之后。<link>
<head>
<link>
const favicon = document.createElement('link')
link.setAttribute('rel', 'favicon icon')
head.appendChild(link)
// Listen media change
window.matchMedia('(prefers-color-scheme:light)')
.addListener((e) => {
if (! e.matches) {
return
}
// Apply new favicon source
const source = document.querySelector('link[rel*="icon",media="(prefers-color-scheme:light)"]')
if (source === null) {
return
}
link.setAttribute('type', source.type)
link.setAttribute('href', source.href)
})
只需复制最后一个表达式并替换light
即可dark
启用黑暗主题图标。
注意!我们检查来源是否是
null
由于可能的 DOM 突变造成的。
结论
现在您知道如何制作页面图标来对主题切换做出反应。
感谢阅读。使用favicon-switcher可以涵盖更多用例,并支持其他媒体查询,例如max-width
、min-width
等。