面向小白的Hexo添加暗色模式教程

美少女万华镜4

OPPO手机都有暗色模式了,你的博客居然还没有。

更新记录

改为给body加class的方式实现暗色模式,同时适配css媒体查询

封面与内容无关,我找不到好看的封面图了。555

写在开头:valine真是让我无语了。这篇文章一直出不来评论框,找了10几分钟原因发现是代码块里不能写注释。。

暗色模式===深色模式==夜间模式!=护眼模式。护眼模式就是让屏幕变屎黄色的那个,减少蓝光,然鹅我晚上还是熬夜。

在tg群看见别人给博客加上了暗色模式,搜索一番得出下面几个方案。

  • prefers-color-scheme 媒体查询
  • 给body加class
  • disabled配合备用css

虽然媒体查询的方法好用,但是 不兼容低版本浏览器和系统。我安卓9有暗色模式也不行。

disabled配合备用css 之前我用的就是这个方法,不需要动原css 操作方便,缺点就是增加了一个请求,并且按钮第一次点击没反应。

如果 只适配系统自带暗色模式,只需要在主题原css里加上如下内容。

1
2
3
@media (prefers-color-scheme: dark) {
这里写要覆盖元素的css
}

也可以配合css变量,让css维护更方便。等过2年等大部分人的设备跟上来。这个媒体查询才能香起来。

我需求比较奇怪,时间范围,按钮开关,适配媒体查询全都要。。最后参照几篇博客的文章折腾了一下。接下来是我自己主题的使用的方法,现在采用的是给body加class的方法。再原css里加上如下内容。

1
2
3
4
5
6
7
8
9
@media (prefers-color-scheme: dark) {
html {
content: "dark";
}
}
body.dark .aplayer{background: #2f3742!important;}
body.dark img {
filter: brightness(50%);
}

在编写暗色模式的样式时,在样式选择器前加 body.dark即可。像aplayer valine基本都要加!important才能让css生效。

在主题的layout.ejs文件中找到body标签的开始标签在后面加如下内容。

1
2
3
4
5
6
7
8
9
10
<script>
var mode = getComputedStyle(document.documentElement).getPropertyValue('content');
if (localStorage.getItem('dark') === '1') {
document.body.classList.add('dark');
} else if (new Date().getHours() >= 22 || new Date().getHours() < 7) {
document.body.classList.add('dark');
} else if (mode == '"dark"') {
document.body.classList.add('dark');
}
</script>

手动,时间范围,媒体查询我都用了。有不需要的部分自行删减。必须得是body开始标签后面,放head里不行,因为文档还没有渲染到body,放太后面会导致页面闪白时间太长。没有使用pjax的博客建议不要给背景色变化加过渡,静态博客每个页面都是独立的,加了过渡动画会导致每次切换页面都有过渡。

屏幕左下角的小埋是手动开关,想起以前看到过别人博客底部的蕾姆,拉姆的至顶至底正好合适拿来作夜间模式开关,翻友链里别人的博客,雷姆没有找到,小埋倒是有一只。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="xm">
<img src="/images/xm.png">
</div>
<script>
function switchNightMode() {
var isDark=$('body').hasClass('dark');
if (isDark) {
document.body.classList.remove('dark');
localStorage.setItem('dark','0');
}else{
document.body.classList.add('dark');
localStorage.setItem('dark','1');
}
}
$(".xm").click(switchNightMode);
</script>

如果你博客没有jQuery使用如下方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
function switchNightMode() {
var body = document.body;
if(body.classList.contains('dark')){
document.body.classList.remove('dark');
localStorage.setItem('dark','0');
}else{
document.body.classList.add('dark');
localStorage.setItem('dark','1');
}
}
var xm = document.getElementById("xm");
xm.onclick = switchNightMode;
</script>

这部分放到layout这个文件的body里就可以。js放在body底部或者外链都可以。小埋的图右键从我这里另存为就可以了。自己搞个喜欢的按钮也行。

按钮的css

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
#xm {
cursor: pointer;
position: fixed;
bottom: 0;
left: 0;
z-index: 1;
font-size: 0;
-webkit-transition: all 0.3s ease-in-out;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
-webkit-transform: translateY(3px);
-webkit-transform: translateY(3px);
-moz-transform: translateY(3px);
-ms-transform: translateY(3px);
transform: translateY(3px);
}
#xm:hover {
-webkit-transform: translateY(0);
-webkit-transform: translateY(0);
-moz-transform: translateY(0);
-ms-transform: translateY(0);
transform: translateY(0);
}
#xm img {
width: 50px;
}

同样是白色 #fff 在chrome下比firefox更暗,firefox不支持改变滚动条样式,简直丑爆了。

之前用sessionCookie在电脑上正常,关闭浏览器会自动删除,但是手机上QQ浏览器和最新的webview都好像没有立即删除。hexo虽然没有后端,但是sessionCookie灵活一些(会话结束立即删除,可以设置过期时间)。改为尝试SeesionStorage,电脑和手机上的QQ浏览器都达到了想要的效果,但webview上每个页面都重新初始化。最后只得改用LoaclStorage。

同一个局域网内,hexo s 后在手机浏览器打开 http://192.168.xxx.xxx:4000 就可以在手机上预览效果。xxx为你自己电脑在局域网内的ip。

折腾时参考过的文章如下