Non-Profit, International

Spirit unsterblich.

通过 JavaScript 给网站切换夜间模式

字数统计:894 blog

最近突发奇想想给博客做个夜间模式。

网络上有很多傻瓜化方法,比如 darkmode.js,但是他的默认样式在我的博客网站上实在是非常糟糕,并且并不能很方便的更改样式。

还有其他方法比如给 <body> 添加 class 再用 css 选择器实现样式的更换。

我注意到了 HTML5 增加了媒体查询和媒体监听器,以及通过 alternate 属性值来控制 css 显示/隐藏的方法,于是就有了下面这个简单的夜间主题控制器。

只需要 2 步即可。

  1. 添加以下内容到你的网页上的 <head> 元素,darkmode.css 是用于实现夜间模式的外部css文件,注意引入顺序带来的优先级问题。

    
     <!-- Darkmode Copyright 2021 YexuanXiao under MIT license -->
     <link rel="alternate stylesheet preload" as="style" href="darkmode.css" id="darkmode-css">
     <script>
         // init darkmode
         {
             const darkmodeCss = document.getElementById('darkmode-css')
             const media = window.matchMedia('(prefers-color-scheme: dark)')
             const time = new Date().getHours()
             if (media.matches || ((time > 20 || time < 6) && sessionStorage.getItem('darktheme') !== 'false')) {
                 darkmodeCss.rel = 'stylesheet'
                 sessionStorage.setItem('darktheme', 'true')
             } else if (sessionStorage.getItem('darktheme') === 'true') {
                 darkmodeCss.rel = 'stylesheet'
             } else {
                 sessionStorage.setItem('darktheme', 'false')
             }
             media.addEventListener('change', () => {
                 media.matches ? darkmodeCss.rel = 'stylesheet' : darkmodeCss.rel = 'alternate stylesheet'
             })
         }
     </script>
    
    

    我建议你将它添加到 <head> 里的原因是这样可以让主题切换迅速,做到访问页面就可以直接显示夜间主题 ,而不会因为 css 渲染顺序的问题导致出现多余的颜色的画面。

    这部分就可以实现按时间和浏览器行为自动切换夜间主题,并且会查询 cookie 中的 theme,通过值来自动切换。

  2. 引入或者添加 darkmode.js,内容为

    
     // Darkmode Copyright 2021 YexuanXiao under MIT license
     // darkmode method
     function changeTheme() {
         const darkmodeCss = document.getElementById('darkmode-css');
         if (sessionStorage.getItem('darktheme') !== 'true') {
             darkmodeCss.rel = 'stylesheet'
             sessionStorage.setItem('darktheme', 'true')
         } else {
             darkmodeCss.rel = 'alternate stylesheet'
             sessionStorage.setItem('darktheme', 'false')
         }
     }
        
     // initlize darkmode button
     {
         const container = document.createElement('div');
         const btn = document.createElement('input');
         document.body.appendChild(container)
         container.appendChild(btn)
         btn.addEventListener('click', changeTheme)
         btn.type = 'button'
         btn.value = '🌓'
         btn.style.cssText = 'background-color: transparent !important; border: none; font-size: 25px; z-index: 999; position: fixed; right: 10%; bottom: 10%'
     }
    
    

    第一部分是更换主题的方法,第二部分是动态创建切换主题的按钮。

最后修改:2021-06-26

若无特殊声明,本文以 CC BY-SA 3.0 许可协议 提供。