网页明暗模式切换的原生代码

Aug 31, 2022 Homecat

实现网页明暗模式的切换有多种方式,各有优缺点,可有个人喜好选择使用。本文记录通过 html、css 和 javascript 三种语言实现切换功能的基本思路和代码。

基本思路

  • 定义明暗两种模式:分别为 light 和 dark;其中 dark 表示暗模式,并且作为默认模式。
  • <html> 元素内添加自定义属性 data-theme,当 data-theme = dark 时,页面渲染为暗模式;当 data-theme = light 时,渲染为明模式。
  • 在 body 体内添加切换点,点击后触发切换。
  • 在 css 的根元素 :root 里分别定义两种模式的属性。
  • 在 javascript 中,添加切换点的监听和动作,用于改变 data-theme 的值。

实现

HTML

 1<!DOCTYPE html>
 2<html data-theme="dark">
 3    <head>
 4        ...
 5    </head>
 6    <body>
 7        ...
 8        <div id="modeToggle">Mode Toggle</div>
 9        ...
10    </body>
11</html>

CSS

 1:root[data-theme="light"] {
 2    --bg-base: white;
 3    --ft-base: black;
 4}
 5
 6:root[data-theme="dark"] {
 7    --bg-base: black;
 8    --ft-base: white;
 9}
10
11body {
12    background-color: var(--bg-base);
13    color: var(--ft-base);
14}

JAVASCRIPT

1const modeToggle = document.getElementById("modeToggle");
2modeToggle.addEventListener("click",()=>{
3    const currentMode = document.documentElement.getAttribute("data-theme");
4    const targetMode = currentMode === "light" ? "dark" : "light";
5    document.documentElement.setAttribute("data-theme",targetMode);
6});

优化

通过上述实践,实现了页面明暗模式的切换,但是只适用于单页面网站。当页面跳转时,页面会重新渲染,切换后的模式不会带入到新的网页中;使用 Web API 接口对象 Window.sessionStorage 对 javascript 文件进行优化。

 1if (sessionStorage.getItem('mode')) { 
 2    document.documentElement.setAttribute("data-theme",sessionStorage.getItem('mode'));
 3}
 4
 5const modeToggle = document.getElementById("modeToggle");
 6modeToggle.addEventListener("click",()=>{
 7    const currentMode = document.documentElement.getAttribute("data-theme");
 8    const targetMode = currentMode === "light" ? "dark" : "light";
 9    document.documentElement.setAttribute("data-theme",targetMode);
10    sessionStorage.setItem("mode",targetMode);
11});

进一步优化

优化后,切换后的明暗模式被带入到新的页面,但是还存在一个问题:每次页面跳转时,会出现一次跳闪。这是因为页面刷新时,先渲染默认的明暗模式,然后再改变为需要的明暗模式。

解决的方法是将 javascript 文件中,判断明暗模式的语句,转移到 <head> 元素里。这样就可以在渲染页面之前就修改参数,直接渲染为需要的明暗模式。

HTML

 1<!DOCTYPE html>
 2<html data-theme="dark">
 3    <head>
 4        ...
 5        <script>
 6            if (sessionStorage.getItem('mode')) { 
 7                document.documentElement.setAttribute("data-theme",sessionStorage.getItem('mode'));
 8            }
 9        </script>
10        ...
11    </head>
12    <body>
13        ...
14        <div id="modeToggle">Mode Toggle</div>
15        ...
16    </body>
17</html>

JAVASCRIPT

1const modeToggle = document.getElementById("modeToggle");
2modeToggle.addEventListener("click",()=>{
3    const currentMode = document.documentElement.getAttribute("data-theme");
4    const targetMode = currentMode === "light" ? "dark" : "light";
5    document.documentElement.setAttribute("data-theme",targetMode);
6    sessionStorage.setItem("mode",targetMode);
7});

参考