原理
先说一下效果:实现了两种模式(这里都是基于 Typecho 博客来测试的)
- 支持用户选择跟随系统模式自动变化的自动模式
- 支持用户手动切换深色模式与浅色模式
下面简单说一下原理,方便理解
1、标志
这里在 <body>
上设置了三种标志用于区分,data-theme="auto"
、data-theme="light"
和 data-theme="dark"
2、逻辑
用户第一次访问网站,默认是 auto
模式,此时网站是切换为深色模式还是保持不变,由系统是否处于深色模式决定
当用户手动切换模式后,data-theme="light"
或者 data-theme="dark"
,此时网站主题不再跟随系统变化
CSS 部分
自己修改网站的 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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| :root { --color-white: #fff; --color-red: #c00; --color-gray: #999999; --color-yellow: #ffc93e; --color-hightlight: #f47466; }
body[data-theme='auto'] { --color-background: #f5f5f5; --color-fontcolor: #363636; --color-url: #3354aa; --color-url-hover: #444; --color-code: #f3f3f3; } @media (prefers-color-scheme: dark) { body[data-theme='auto'] { --color-background: #2c2a2a; --color-fontcolor: #d5d5d5; --color-url: #f0f0f0; --color-url-hover: #8ab4f8; --color-code: #b0b0b0; } }
body[data-theme='light'] { --color-background: #f5f5f5; --color-fontcolor: #363636; --color-url: #3354aa; --color-url-hover: #444; --color-code: #f3f3f3; }
body[data-theme='dark'] { --color-background: #2c2a2a; --color-fontcolor: #d5d5d5; --color-url: #f0f0f0; --color-url-hover: #8ab4f8; --color-code: #b0b0b0; }
body { background-color: var(--color-background); color: var(--color-fontcolor); }
|
记录一下 SCSS 写法
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
| @mixin light { --color-mode: 'light'; --color-bg: #fffffd; }
@mixin dark { --color-mode: 'dark'; --color-bg: #2f3136; }
body[data-theme='auto'] { @include light();
@media (prefers-color-scheme: dark) { @include dark(); } }
body[data-theme='light'] { @include light(); }
body[data-theme='dark'] { @include dark(); }
body { background-color: var(--color-bg); }
|
HTML
用 Typecho 博客举例,修改 header.php
文件
因为 php 可以和 Cookie 交互,所以用户选择的主题保存到了 Cookie 中(如果不用 PHP 的话,可以使用 JS 来实现,数据也可以储存到 localStorage)
在 <body>
处添加 php 代码
1 2 3 4 5 6 7 8 9 10 11
| <?php if($_COOKIE["data-theme"]=='light') { echo "light"; } elseif($_COOKIE["data-theme"]=='dark'){ echo "dark"; } else{ echo "auto"; } ?>
|
完整的写法,如果 Cookie 里没有值,默认是第一次进入,选择 auto,否则主题由 Cookie 里面的值决定
1 2 3 4 5 6 7 8 9 10 11
| <body data-theme="<?php if($_COOKIE["data-theme"]=='light') { echo "light"; } elseif($_COOKIE["data-theme"]=='dark'){ echo "dark"; } else{ echo "auto"; } ?>">
|
JavaScript
使用 Typecho 博客的话,可以放到 footer.php
的 </body>
标签前面
或者保存为 js
文件外部引用,然后就完工了。
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 48
| cookiesExp = new Date(new Date().setMonth(new Date().getMonth() + 1))
function getNowTheme() { let nowTheme = document.body.getAttribute('data-theme') if (nowTheme === 'auto') { return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' } else { return nowTheme === 'dark' ? 'dark' : 'light' } }
var navFn = { switchDarkMode: function () { let nowTheme = getNowTheme() let domTheme = document.body.getAttribute('data-theme')
if (domTheme === 'auto') { let theme = nowTheme === 'light' ? 'dark' : 'light' document.body.setAttribute('data-theme', theme) document.cookie = 'data-theme=' + theme + ';path=/' + ';expires=' + cookiesExp
} else if (domTheme === 'light') { document.body.setAttribute('data-theme', 'dark') document.cookie = 'data-theme=dark;path=/' + ';expires=' + cookiesExp
} else { document.body.setAttribute('data-theme', 'light') document.cookie = 'data-theme=light;path=/' + ';expires=' + cookiesExp } }, }
var autoFn = { switchAutoMode: function () { document.body.setAttribute('data-theme', 'auto') document.cookie = 'data-theme=auto;path=/' + ';expires=' + cookiesExp }, }
|
简单的一个文字引用
1 2
| <a class="darkmode_switch" onclick="navFn.switchDarkMode()">Dark</a> <a class="auto_switch" onclick="autoFn.switchAutoMode()">Auto</a>
|
参考
更新深色模式主题并支持 prefers-color-scheme,作者:DSRKafuU