menu FlyingSky's Blog
more_vert

动态

恰饭位

爱发电

热门文章

最新文章

最近回复

标签

网站统计

chevron_right 首页 » 网站 » 正文
给博客添加 DARK Mode ( 黑暗模式 )
January 29th, 2019 | 网站 | 23 条评论 | 3071 次阅读

这个月 LinusTechTips 怼出了一期视频专门讲了讲 "DARK Mod" ,确实,夜间刷刷刷的时候还是黑底白字看起来更顺眼一点。这回,我来给博客加上夜间模式,加入 Deep♂Dark♂Family (咳咳咳皮了)。

HeadPic

看到右下角的“暗”按钮了吗?点击它,开始你的黑暗之旅吧!

思路

本质上讲,Dark Mode 就是在指定时间段内修改页面配色、图片亮度等,既然是动态修改的,就免不了要用到 JavaScript 了。

样式有三种书写形式,分别为外联 ( 额外的 .css 文件,在 HTML 中使用 <link rel="stylesheet" href="..."> 建立连接 ) 、内联 ( 使用 <style>...</style> 将样式写在 HTML 中 ) 和内嵌 ( 在元素上使用 style="..." ) 。使用 JS 修改样式,就有以下三种方式进行操作:

1.引入一个新的外联 CSS 文件,以覆盖原有样式 ( 不影响原有样式文件、方便维护 ) 。
2.在原有 CSS 上追加样式,以 class 名区分 ( 方便 JS 操作,实现优雅、方便维护 ) 。
3.直接修改元素的 style 属性,即内嵌样式 ( 不推荐 ) 。

在这里博主选用第二种方法。

实现

使用 JS 控制元素 class

JSElement.classListadd()remove() 方法,正好满足我们的需求,且支持绝大多数浏览器支持。但先别急着写,还有一个细节:夜间模式这个状态应被保存下来一直生效,或持续到本次会话 Session 结束,cookie 可以满足我们的要求。

所以事情就很明朗了,编写代码:

function switchDarkMode(){
    var night = document.cookie.replace(/(?:(?:^|.*;\s*)dark\s*\=\s*([^;]*).*$)|^.*$/, "$1") || '0';
    if (night == '0'){
        document.body.classList.add('dark');
        document.cookie = "dark=1;path=/";
        console.log('Dark mode on');
    }else{
        document.body.classList.remove('dark');
        document.cookie = "dark=0;path=/";
        console.log('Dark mode off');
    }
}

即可实现夜间模式的 切换状态保存

在指定时间段内修改

思路很简单,页面加载后判断时间,在指定范围内修改元素 class

(function(){
    if(document.cookie.replace(/(?:(?:^|.*;\s*)dark\s*\=\s*([^;]*).*$)|^.*$/, "$1") === ''){
        if(new Date().getHours() > 22 || new Date().getHours() < 6){
            document.body.classList.add('dark');
            document.cookie = "dark=1;path=/";
            console.log('Dark mode on');
        }else{
            document.body.classList.remove('dark');
            document.cookie = "dark=0;path=/";
            console.log('Dark mode off');
        }
    }else{
        var dark = document.cookie.replace(/(?:(?:^|.*;\s*)dark\s*\=\s*([^;]*).*$)|^.*$/, "$1") || '0';
        if(dark == '0'){
            document.body.classList.remove('dark');
        }else if(dark == '1'){
            document.body.classList.add('dark');
        }
    }
})();

具体的样式内容

在上面的代码中,我们控制了 <body> 元素的 class,这是所有页面元素的祖先元素。启用夜间模式时,<body>class 值含有 dark ( 即 <body class="dark"> ) 。因此在编写夜间模式的样式时,在样式选择器前加 body.night 即可,可酌情使用 !important

图片亮度

使用 CSS 滤镜中的 brightness() 滤镜 ( 仅支持现代浏览器 ) 可以实现:

body.night img {
    filter: brightness(50%);
}

后端处理

因为是在本地通过 JS 操控样式,所以在 JS 加载前后样式不一样,会导致页面闪烁 然后闪瞎。可在博客主题中加上判断,当检测到 cookie含有相关字段后可直接输出 <body class="dark"> ,如:

<body class="<?php if($_COOKIE['dark']=='1'){echo'dark';} ?>">

加个按钮

这个就随网站样式而定啦,只要在元素上加上 onclick="switchDarkMode()" 就行了。

动态修改按钮内容

你可能注意到了,本站右下角的 Dark Mode 切换按钮上的字是会变的,即在 Dark Mode 开启时显示“亮”,关闭时显示“暗”,其实用 innerHTML 就可以更改啦。这样的话就需要在按钮元素上加个 id="..." ,然后在 JS 上加行代码。

跨域使用

如果您有多个站点都要设置上 Dark Mode ,又不想让用户在切换站点后重新开关 Dark Mode ( 即多站点的 Dark Mode 开关设定统一 ) ,这时,您可以通过设置 Cookie 作用域实现它。

Cookie 可以设置作用路径和作用域,限定 Cookie 的生效范围。目前来说,最大的作用范围就是整个域名 ( 比如 fsky7.com ) ,这样该域名下所有主机的所有位置 ( 比如 blog.fsky7.comboard.fsky7.com/ssl ) 都能获取该 Cookie

JavaScript 里,在 Cookie 内容后面加上 domain=... 即可,比如我们这次实现用到的代码:

document.cookie = "dark=1;path=/;domain=fsky7.com";
...
document.cookie = "dark=0;path=/;domain=fsky7.com";

( 拓展:PHP 中设置 Cookie 的操作是 setcookie(name, value, expire, path, domain); ,可以在最后一个参数里面设置作用域 )

所以,实现这个方法只需要在每个 document.cookie 的值后面加上作用域即可。

如果您使用的是 Initial 主题 可以直接参考 Initial 简约主题的本站食用方式 -> 实用功能 -> 黑暗模式

实时更新

使用场景:访问者同时打开了两个分别为不同站点的标签页 ( 比如 https://blog.fsky7.com/archives/46/https://board.fsky7.com/ssl/ ) ,访问者在其中一个标签页更开关了 Dark Mode ,然后切换到了另一个标签页,这个功能让另一个标签也同步更新 Dark Mode 的开关情况。

Show

实现方式:加一串 JavaScript 代码,使其在切换标签页时进行判断。

document.addEventListener('visibilitychange', function () {
    var dark = document.cookie.replace(/(?:(?:^|.*;\s*)dark\s*\=\s*([^;]*).*$)|^.*$/, "$1") || '0';
    if(dark == '0'){
        document.body.classList.remove('dark');
        document.getElementById("darkmode").innerHTML="暗";
    }else if(dark == '1'){
        document.body.classList.add('dark');
        document.getElementById("darkmode").innerHTML="亮";
    }
});

给滚动条也适配上

感谢 Nanlon 提出的要求。

这个可以通过 ::-webkit-scrollbar 实现。

-
::-webkit-scrollbar 仅仅在支持 WebKit 的浏览器 (例如, Chrome, Safari) 中使用
-

请参见文章:::-webkit-scrollbar。本站的食用方式看下一节。

本站的食用方式

请参见文章:Initial 简约主题的本站食用方式 -> 实用功能 -> 黑暗模式

鸣谢

本文参考由 journey.ad 创作的文章 给博客添加夜间模式 - 猫与向日葵 ,原文使用 知识共享署名 4.0 国际 (CC BY 4.0) 许可协议进行许可,本文的部分内容使用了该文章部分内容且进行了部分修改。

文章目录
文章目录

标签: 博客, 夜间模式, DARK, LinusTechTips, Dark mode

已有 23 条评论

    云武
    云武
    August 26th, 2019 at 10:00 pm

    问个问题,代码和CSS都弄好以后使用没问题了,但我的网页白色样式F5刷新的时候明显能看到晚上的样式会唰的一下闪一下,啥原因呢?

      FlyingSky
      FlyingSky 博主
      August 27th, 2019 at 02:37 pm

      请先参考 本文章 -> 实现 -> 后端处理 章节,有提到这个问题。并且建议将 Dark Mode 的 CSS 代码放在所有 CSS 代码的最前面。

        云武
        云武
        August 27th, 2019 at 03:28 pm

        找到问题了。Chrome 会闪但重启好了,Firefox 不会。

    wangy
    wangy
    April 17th, 2019 at 09:59 am

    wordpress中能用否?

      FlyingSky
      FlyingSky 博主
      April 17th, 2019 at 08:17 pm

      都能用哦

    阿文
    April 11th, 2019 at 09:33 am

    不错哦,就是太麻烦了

    FlyingSky
    FlyingSky 博主
    March 21st, 2019 at 07:06 pm

    文章更新日志 March 21st, 2019.

    新增 实现->给滚动条也适配上

    Nanlon
    March 17th, 2019 at 12:59 pm

    怎样才能给滚动条也是用 Dark Mode 呢?比如 pre 中的

      FlyingSky
      FlyingSky 博主
      March 21st, 2019 at 07:05 pm

      搞定啦!

    FlyingSky
    FlyingSky 博主
    March 16th, 2019 at 08:19 pm

    文章更新日志 March 16th, 2019.

    更新 实现->本站的食用方式
    新增 实现->跨域使用
    新增 实现->跨域使用->实时更新

    小石
    February 14th, 2019 at 02:44 pm

    不错,看起来真舒服

    派兹
    February 3rd, 2019 at 11:00 pm

    打开Dark Mode之后 Chrome的标题栏还是亮的 可以用theme color改成黑色的(

      FlyingSky
      FlyingSky 博主
      February 11th, 2019 at 09:05 pm

      Chrome Android 限定(?

    share1223
    February 3rd, 2019 at 10:02 am

    能不能出个插件什么的 我按照你方法 就是报错 我是小白

      FlyingSky
      FlyingSky 博主
      March 7th, 2019 at 08:07 pm

      您该不会是把 JavaScript 当成 PHP 了吧

      share1223
      February 12th, 2019 at 11:18 am

      就是网站打不开,可能是主题问题,不兼容吧 有冲突 自己也不清楚是哪里

      FlyingSky
      FlyingSky 博主
      February 3rd, 2019 at 10:26 am

      可以提供下报错内容吗?

    半步
    半步
    February 1st, 2019 at 10:43 pm

    不错

添加新评论

© 2019 FlyingSky. Powered by Typecho & MDr.
博客已上线 .
brightness_4