Silence 主题暗黑模式根据浏览器配置,以及切换页面闪白屏的问题处理
最近使用 Silence v3.0.0-rc2 主题遇到两个偏好问题(感谢作者提供了这么好用的主题),记录下处理的过程。
暗黑/亮色模式跟随浏览器的主题切换
由于主题当前支持的配置项 auto
是根据时间定的,而不是根据浏览器的配置来的,而我个人偏向于跟随浏览器的配置来自动设置,于是用 js
先判断浏览器的配置,再将模式配置到 slience
中,具体如下:
在页脚 HTML
代码中的配置项下面加入:
// 判断当前浏览器的模式是否为 light
const themeMedia = window.matchMedia("(prefers-color-scheme: dark)");
// 根据浏览器的配置设置主题
if (themeMedia.matches) {
window.$silence.defaultMode = 'dark';
} else {
window.$silence.defaultMode = 'light';
}
也可以加入监听浏览器的模式变更事件,让页面自动变化:
// 记录是否被手动设置过
let manualSet = false;
// 监听
themeMedia.addEventListener('change', function() {
if (manualSet) {
// 如果有被手动设置过则不处理
return
}
document.querySelector('.mode').click();
manualSet = false;
})
// 监听点击切换模式的事件
// 需要放在 slience 主题 js 文件加载之后
document.querySelector('.mode').addEventListener('click', function () {
manualSet = true
})
暗黑模式下切换页面闪白屏问题
暗黑模式下,页面的切换,比如从主页跳转到文章详情页,或是从文章详情页面跳到主页,页面都会先闪一下白屏,然后再恢复成暗黑的模式,仔细看了下 CSS
定义中 root
的定义:
:root {
--loading-bg-color: #fff
}
:root[mode=light] {
...
--loading-bg-color: #fff
}
:root[mode=dark] {
...
--loading-bg-color: #222
}
推测浏览器渲染应该是先渲染了 root
的样式,再渲染的 root[mode=dark]
的样式,于是将 root
的定义改为暗黑的样式:
:root {
--loading-bg-color: #222
}
果然就不闪白屏了,但是在亮色模式下还是存在,恢复成原来的代码似乎要好一些。为此可以使用 CSS
的条件判断来配置,如果是亮色的话就使用亮色的定义,否则使用暗黑模式的定义,默认定义为亮色:
@media (prefers-color-scheme: dark) {
:root {
--loading-bg-color: #222
}
}
@media (prefers-color-scheme: light) {
:root {
--loading-bg-color: #fff
}
}
@media (prefers-color-scheme: no-preference) {
:root {
--loading-bg-color: #fff
}
}
为了让点击切换主题时也能达到这个效果,这里也可以在配置中加入对主题切换这一操作的监听,每当主题发生变化时就相应的更改 --loading-bg-color
的值,具体如下:
也是在页脚 HTML
代码中的配置项下面加入:
// 在主题切换时更新 loading-bg-color 的值
const root = document.querySelector(':root');
let mode;
function resetRootBgColor(mutationsList, observer) {
let currentMode = $('html').attr('mode');
if (mode === currentMode) {
return
} else {
mode = currentMode;
}
if (currentMode === 'dark') {
root.style.setProperty('--loading-bg-color', '#222');
} else {
root.style.setProperty('--loading-bg-color', '#fff');
}
}
// 加入对主题切换事件的监听
const mutationObserver = new MutationObserver(resetRootBgColor);
mutationObserver.observe($('html')[0], { attributes: true });