使用matchMedia 和prefers-color-scheme,您可以根据用户的系统范围偏好应用默认主题。如果用户启用了根据一天中的时间或通过其设备上的光传感器启用自动切换,这将自动调整。
然后,如果他们选择覆盖它,请将他们的选择保存在 localStorage 中。在用户清除您的源的存储之前,此首选项将保持不变。
<!DOCTYPE html>
<head>
<title> Theme Selector Test </title>
<style>
:root.default { --bgr: #eee; --txt: #000; }
:root.light { --bgr: #ddc; --txt: #446; }
:root.dark { --bgr: #222; --txt: #a75; }
:root.blue { --bgr: #246; --txt: #eec; }
body { background: var(--bgr); color: var(--txt); margin: 1.5rem; }
</style>
<script>
function setTheme(theme) {
if (theme == 'auto') {
localStorage.removeItem('theme');
loadTheme(null);
} else {
localStorage.setItem('theme', theme);
applyTheme(theme);
}
}
function loadTheme(theme) {
let prefersDark = matchMedia('(prefers-color-scheme: dark)');
prefersDark.addEventListener('change', event => loadTheme());
theme = localStorage.getItem('theme');
theme ??= (prefersDark.matches) ? 'dark' : 'default';
applyTheme(theme);
}
function applyTheme(theme) {
document.documentElement.className = theme;
}
window.setTheme = setTheme;
loadTheme();
</script>
</head>
<body>
<h1> Select a theme to change the color scheme! </h1>
<select id="scheme">
<option value="auto">Auto</option>
<option value="default">Default</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
<option value="blue">Blue</option>
</select>
<script>
let selector = document.getElementById('scheme');
selector.value = localStorage.getItem('theme') || 'auto';
selector.addEventListener('click', event => window.setTheme(selector.value));
</script>
</body>
请参阅this answer,了解有关如何模拟系统范围偏好以进行测试的说明。
正如@Anton 所提到的,localStorage 由于沙盒,在 Stack Overflow 上的 sn-ps 中不起作用,因此我将其编写为整页示例,以演示在实际中实现它的最佳方法-世界环境。
我也有 published 的 ES 模块版本。实现本文中演示的内联版本会更好地提高性能,但如果您想避免污染全局范围,则模块版本会更好。
我在示例中使用了<select> 元素,因为这可能是大多数用户在未来发现它时可能想要使用它的方式。要显示您在问题中显示的选项,您可以如下所示实施。请注意,我已将 <p> 标记替换为 <button> 以获得更好的可访问性。我还在单击处理程序中添加了一个额外的检查,以避免在单击容器 <div> 的背景区域时调用 setTheme。
在你的 CSS 中:
#scheme button {
border: 0;
background: none;
color: inherit;
text-decoration: underline;
cursor: pointer;
}
在您的 HTML <body> 中:
<div id="scheme">
<button id="auto">Auto</button>
<button id="default">Default</button>
<button id="light">Light</button>
<button id="dark">Dark</button>
<button id="blue">Blue</button>
</div>
<h1>Click on a theme to change the color scheme!</h1>
<script>
let selector = document.getElementById('scheme');
selector.addEventListener('click', event => {
if (event.target == selector) { return; }
window.setTheme(event.target.id);
});
</script>