以上都不适合我。我决定从不同的角度来处理这个问题。年份是 2021 年。
以下优惠:
- 尊重系统偏好。
- 系统偏好设置被覆盖。
- 尊重滚动条配色方案。
-
通用浏览器支持。(IE 生命周期结束,2021 年 8 月 17 日?✌️?)
当您查看MDN Web Docs page for prefers-color-scheme 时,您可以阅读以下内容:
prefers-color-scheme CSS 媒体功能用于检测用户是否请求了浅色或深色主题。
[...]
light 表示用户已通知他们更喜欢具有浅色主题的界面,或尚未表达积极的偏好。
因此,对于任何浏览器,默认情况下,prefers-color-scheme 要么设置为 light,要么不受支持。
我在接受答案时遇到的一个问题是更改不会影响滚动条颜色。这可以使用与:root 伪元素耦合的color-scheme CSS property 来处理。
我遇到的另一个问题是,如果用户将系统设置更改为亮或暗,则网站不会受到影响,并且会在两种样式之间产生不匹配。我们可以通过将window.matchMedia( '(prefers-color-scheme: light)' ) 耦合到onchange 事件侦听器来修复该行为。
这是最终的脚本。
(() => {
var e = document.getElementById("tglScheme");
window.matchMedia("(prefers-color-scheme: dark)").matches
? (document.head.insertAdjacentHTML("beforeend", '<style id="scheme">:root{color-scheme:dark}</style>'),
document.body.classList.add("dark"),
e && (e.checked = !0),
window.localStorage.getItem("scheme") &&
(document.getElementById("scheme").remove(), document.head.insertAdjacentHTML("beforeend", '<style id="scheme">:root{color-scheme:light}</style>'), document.body.classList.remove("dark"), e && (e.checked = !1)),
e &&
e.addEventListener("click", () => {
e.checked
? (document.getElementById("scheme").remove(),
document.head.insertAdjacentHTML("beforeend", '<style id="scheme">:root{color-scheme:dark}</style>'),
document.body.classList.add("dark"),
localStorage.removeItem("scheme"))
: (document.getElementById("scheme").remove(),
document.head.insertAdjacentHTML("beforeend", '<style id="scheme">:root{color-scheme:light}</style>'),
document.body.classList.remove("dark"),
localStorage.setItem("scheme", 1));
}))
: (document.head.insertAdjacentHTML("beforeend", '<style id="scheme">:root{color-scheme:light}</style>'),
e && (e.checked = !1),
window.localStorage.getItem("scheme") &&
(document.getElementById("scheme").remove(), document.head.insertAdjacentHTML("beforeend", '<style id="scheme">:root{color-scheme:dark}</style>'), document.body.classList.add("dark"), e && (e.checked = !0)),
e &&
e.addEventListener("click", () => {
e.checked
? (document.getElementById("scheme").remove(),
document.head.insertAdjacentHTML("beforeend", '<style id="scheme">:root{color-scheme:dark}</style>'),
document.body.classList.add("dark"),
localStorage.setItem("scheme", 1))
: (document.getElementById("scheme").remove(),
document.head.insertAdjacentHTML("beforeend", '<style id="scheme">:root{color-scheme:light}</style>'),
document.body.classList.remove("dark"),
localStorage.removeItem("scheme"));
}));
})(),
window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", () => {
location.reload(), localStorage.removeItem("scheme");
});
对于 CSS 方面,我们使用默认的 variable custom property values fallback,并将深色放在首位。我们可以通过 :root 元素定义所有必要的深色。
:root body.dark {
--app-bg-dark: #131313;
--app-tx-dark: #f8f9fa;
}
body{
background-color: var( --app-bg-dark, white );
color: var( --app-tx-dark, black );
}
/* if dark mode isn't set, fallback to light. */
对于 html,一个简单的复选框 <input id="tglScheme" type="checkbox">。
最后是 Codepen https://codepen.io/amarinediary/full/yLgppWW。
Codepen 会覆盖location.reload(),因此您将无法测试系统更改的实时更新。不要犹豫,在您的本地主机上尝试一下。