Non-Profit, International

Spirit unsterblich.

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

字数统计:736 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 = 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 4.0 许可协议 提供。