Manual Dark Mode

 

直接了当

本Blog右上角的那个小月亮或者小太阳可以手动自由切换不是吗,稍微谈谈用了什么骚方法改的,以及需要注意什么,参考代码是How to override css prefers-color-scheme setting中的第一个回答

首先需要看看模板是怎么实现的,找了半天发现是纯scss,css的媒体查询,现在需要手动,于是乎改_properties.scss

1
2
3
4
5
6
7
8
9
10
11
12
13
[data-theme="dark"] {
  @each $name, $value in $dark {
    --#{$name}: #{$value};
  }
}

// @media (prefers-color-scheme: dark) {
//   :root {
//     @each $name, $value in $dark {
//       --#{$name}: #{$value};
//     }
//   }
// }

然后需要JS来判断,看看哪里能写,按照模板文档,页面全部都是page的子类,page.js是空的,而且确定被page.html引入了,就直接写里面好了:

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
function getTheme() {
    var theme = "light";    //default to light

    //local storage is used to override OS theme settings
    if (localStorage.getItem("theme")) {
        if (localStorage.getItem("theme") == "dark") {
            var theme = "dark";
        }
    } else if (!window.matchMedia) {
        //matchMedia method not supported
        return false;
    } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
        //OS theme setting detected as dark
        var theme = "dark";
    }
    return theme;
}

function initTheme() {
    //dark theme preferred, set document with a `data-theme` attribute
    if (getTheme() == "dark") {
        document.documentElement.setAttribute("data-theme", "dark");
    }
}
initTheme();

function initThemeSwitch() {
    if (getTheme() == "dark") {
        document.getElementById("themeSwitch1").className = "fas fa-sun";
        document.getElementById("themeSwitch2").className = "fas fa-sun";
    }
}

function toggleTheme() {
    if (localStorage.getItem("theme") == "dark") {
        localStorage.setItem("theme", "light");
        document.documentElement.setAttribute("data-theme", "light");
        document.getElementById("themeSwitch1").className = "fas fa-moon";
        document.getElementById("themeSwitch2").className = "fas fa-moon";
    } else {
        localStorage.setItem("theme", "dark");
        document.documentElement.setAttribute("data-theme", "dark");
        document.getElementById("themeSwitch1").className = "fas fa-sun";
        document.getElementById("themeSwitch2").className = "fas fa-sun";
    }
}

然后请注意,page.html也要改改,要把<script>{ %- include scripts/page.js -% }</script>放到最前面去1,也就是DOM加载前需要运行page.js,还要在DOM加载完后的<script>标签里写一个initThemeSwitch();

最后把图标放进header.html就行,注意有两处,应该是移动端和大屏端两种:

1
2
3
4
5
6
7
<button class="button button--secondary button--circle search-button" onclick="toggleTheme()"><i id="themeSwitch1" class="fas fa-moon"></i></button>
<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>

......

<li><button class="button button--secondary button--circle search-button" onclick="toggleTheme()"><i id="themeSwitch2" class="fas fa-moon"></i></button></li>
<li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li>

补充说明

为什么要调整JS运行顺序呢,因为这样美观(否则在暗黑模式下,刷新或者切换页面会有一丢丢的白天模式的残影闪过,强迫症很难受

那直接放前面就好了啊,为什么要分开呢?因为DOM没加载完也改不了那两个按钮的class啊,这是遗憾的地方(眼力够好还是能发现一点点图标切换的残影)

有更好的办法快告诉我(

  1. 这里花括号两边多了两个空格,否则会被编译(什么注入漏洞