移动HTML的高效暗模式主题与切换



我一直在寻找拥有移动高效的方法暗模式主题,即是自动的,可以切换。我说的移动高效是指高延迟、低带宽、低cpu友好:

  • 只加载相关的样式表(当激活浅色样式表时,不加载深色样式表,反之亦然)以节省带宽
  • 无全屏闪烁
  • 没有饼干

我发现的解决方案没有这些属性,他们要么使用两个主题结合的胖CSS,要么使用两个样式表,当用户选择与系统默认值不同的主题时,这可能导致全屏闪烁(因为它们是通过JS执行控制的样式表在DOM中被引用)。

到目前为止,我最好的选择是"高效",但依赖于文档。在文档头部写一个小的内联脚本,如下所示:
let theme = localStorage.getItem("theme");
if (!theme) {
theme = (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches)?"dark":"light"
}
if (theme == "dark") {
document.write('<link rel="stylesheet" href="dark.theme.css" />');
} else {
document.write('<link rel="stylesheet" href="light.theme.css" />');
}

localStorage条目由用户手动切换时由常规JS管理。

我已经尝试了所有的方法来改变链接DOM元素,他们都失败了,导致闪烁或延迟CSS加载(与未呈现的HTML是暂时可见的)。

我想知道是否有一种方法仍然是有效的,支持切换,不依赖于文档。写什么?

添加一个类" is-dark ";到HTML标签?为了使css尽可能简洁,可以将所有颜色定义为css自定义属性,并在"is-dark"范围内重新定义它们。因此,您只需要交付这些自定义属性两次,这应该是可管理的。

你仍然需要JS来添加类,但是你不需要document.write。这将在三种情况中的两种情况下消除闪烁,即通过媒体查询选择深色主题和使用开关选择深色主题。

那么它看起来就像这样:

:root {
--clr-primary:                      #8e211a;
--clr-secondary:                    #5e737a;
…
}

.is-dark {
--clr-primary:                      black;
--clr-secondary:                    white;
}

.myElement {
color: var(--clr-secondary);
background-color: var(--clr-primary);
}

这就给我们留下了第三种情况的问题:当在重新加载之前每个开关都选择了黑暗主题时,重新加载后会闪烁。在这种情况下,浅色主题将被使用,直到JS点击并切换到深色主题。

最好的选择似乎是阻止页面渲染,直到JS准备就绪,如这个线程所示:黑暗模式在重新加载

时闪烁一毫秒的白色背景

最新更新