html - 使用移动 HTML 切换的高效暗模式主题
问题描述
我一直在寻找拥有移动高效黑暗模式主题的方法,它既是自动的,又可以切换。移动效率是指高延迟、低带宽、低 CPU 友好:
- 只加载相关的样式表(当灯光处于活动状态时,不加载深色样式表,反之亦然)以节省带宽
- 没有全屏闪烁
- 没有饼干
我发现的解决方案没有这些属性,它们要么使用结合了两个主题的胖 CSS,要么使用两个样式表,当用户选择与系统默认不同的主题时,这可能会导致全屏闪烁(因为它们是通过在 DOM 中引用样式表后执行的 JS 来控制的)。
到目前为止,我最好的选择是“高效”,但依赖于 document.write 在文档头中的一个小内联脚本中,它类似于:
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 暂时可见)。
我想知道是否有一种方法仍然有效,支持切换而不依赖 document.write ?
解决方案
在 html 标签中添加一个“is-dark”类怎么样?为了使您的 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 准备好之前阻止页面渲染,如此线程所示:Dark mode flickers a white background for a millisecond on reload
推荐阅读
- wpf - 离开页面时如何销毁页面上的所有数据
- ruby - Sidekiq drain 还执行通过 perform_in 排队的新作业
- java - 用于检查 JSON 字段值的 Hamcrest 匹配器是空还是空?
- php - 错误:调用未定义的函数 curl_version() PHP Stripe
- javascript - 将具有两个元素的数组转换为具有一个 k/v-pair 的 JS 对象
- android - 我如何通过一个意图共享纯文本和另一个文件(如 excel 文件)
- r - R - 在使用调查包时制作 ggplot
- xml - PowerShell - XML - 处理具有和不具有属性的节点
- java - 前台服务一段时间后关闭
- python - 如何使用 Python 分析 SQL 查询?