DarkReader API

很早之前用的客户端暗色插件现在支持服务端调用了 DarkReader API 那么正好写一个设置来支持切换深浅色模式,以及持久化用户设置。DarkReader 真的非常方便,理论上默认设置都能很好自动渲染网页生成对应的 CSS,如果有不正常的地方自己微调一下就行。

Setting Page

首先得有一个开关或者设置,这里我选择自己写了一个 Setting 用于存储用户数据,还有保存到 localStorage 之类的的( ) 这里初始化了一个按键的开关,作为被绑定的载体。

Toggle

1
2
3
4
5
6
7
8
<div class="setting-item">
<label for="theme-toggle" class="setting-label"><strong>Dark Mode</strong>:</label>
<span class="setting-description">Toggle the dark theme. It will sync with your system theme settings the first time.</span>
<label class="switch">
<input type="checkbox" id="theme-toggle">
<span class="slider round"></span>
</label>
</div>

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
window.onload = function() {
const cookieStatus = localStorage.getItem('allowCookies') === 'true';
const themeStatus = localStorage.getItem('darkMode') === 'true';

document.getElementById('cookie-toggle').checked = cookieStatus;
document.getElementById('theme-toggle').checked = themeStatus;

// Load dark mode settings from localStorage or auto
const darkModeStatus = localStorage.getItem('darkMode');
if (darkModeStatus !== null) {
if (darkModeStatus === 'true') {
DarkReader.enable({ brightness: 100, contrast: 100, sepia: 0 });
} else {
DarkReader.disable();
}
} else {
DarkReader.auto({ brightness: 100, contrast: 90, sepia: 10 });
localStorage.setItem('darkMode', DarkReader.isEnabled().toString());
}
};

// Dark mode toggle
document.getElementById('theme-toggle').addEventListener('change', function() {
const isDarkMode = this.checked;
localStorage.setItem('darkMode', isDarkMode.toString());
if (isDarkMode) {
DarkReader.enable({ brightness: 100, contrast: 100, sepia: 0 });
} else {
DarkReader.disable();
}
});

上面的 JS 调用的 window.onload 只是为了设置界面可以正常生效,并且持久化和每次自动从 localStorage 加载按键信息所用的,具体的全局设置可以参考这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html lang="{{ config.language }}">
<head>
{% include "_partial/head.swig" %}
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<script>
(function() {
const darkModeSetting = localStorage.getItem('darkMode');
if (darkModeSetting === 'true') {
DarkReader.enable({
brightness: 100,
contrast: 100,
sepia: 0
});
}
else if (darkModeSetting === 'false') {
DarkReader.disable();
}
else {
DarkReader.auto({
brightness: 100,
contrast: 90,
sepia: 10
});
}

const isEnabled = DarkReader.isEnabled();
localStorage.setItem('darkMode', isEnabled.toString());
})();
</script>
<div class="container">
{% include "_partial/header.swig" %}
<div class="container-inner" style="display:none;">
<main class="main" id="main">
<div class="main-wrapper">
{% block main %} {% endblock %}
</div>
</main>
{% include "./_partial/footer.swig" %}
</div>
{% include "./_partial/tagcloud.swig" %}
</div>
{% include "_partial/_feature/common.swig" %}
</body>
</html>

这里我之前踩过坑,那就是在最开始调用这个 JS 会导致加载过早, 导致后面渲染出来的页面完全没有被应用深色模式,如果用 window.onload 会导致深色模式的一瞬间加载的时候实际上是浅色主题,等加载完后才执行的 API, 所以你应该把这段 JS 塞在 _layout.swig 或者你使用的框架的合适地方, 比如整体 Web Body( )