【问题标题】:Is it possible to use JavaScript to switch between light mode and darkmode on a page?是否可以使用 JavaScript 在页面上的浅色模式和深色模式之间切换?
【发布时间】:2021-04-18 13:50:34
【问题描述】:

我可以使用

@media (prefers-color-scheme: dark)

window.matchMedia('(prefers-color-scheme: dark)').matches

检测操作系统是否为暗模式。

但是,有什么方法可以让我使用 JavaScript 自行修改状态?这样我就可以创建一个按钮,让用户在不想保留操作系统设置时在明暗之间切换。

【问题讨论】:

  • 你不能改变prefers-color-scheme的值,但是你可以使用类和其他方法来为你的网站提供亮模式和暗模式。
  • 不,您不能在网页上下文中通过脚本修改这种设置。您可以为此使用一个附加类,它会覆盖由这些媒体查询确定的样式 - 但取决于您需要更改多少格式,您最终可能会将大量代码加倍。 (不能同时使用一个规则,但必须重复所有样式,一次在 @media() { … } 内,一次在 .myspecialclass { … } 内)
  • (除非可以在媒体查询说明符内部使用CSS变量,但我认为这实际上不可能?)
  • 会有drafts.csswg.org/mediaqueries-5/#script-custom-mq,它允许将样式块设置为两个媒体查询,但它没有在任何地方实现,而且真的不清楚它是否会实现。

标签: javascript browser ios-darkmode android-darkmode macos-darkmode


【解决方案1】:

也许支持深色模式的最简单方法是为浅色主题定义文本、背景、边框、阴影等的所有颜色设置,然后使用媒体查询覆盖颜色,但正如您所说,这不会让您的访问者选择切换。

为了给访问者一个选择,您可以在页面上添加一个不显眼的小开关(一些网站,例如 GitHub 在其桌面版本上显示一个开关,但要在移动设备上打开,用户必须打开设置功能)。

我所做的是将用户的偏好保存在 localStorage 中,并在他们下次回来时遵循存储的偏好(即使他们已经更改了系统设置)。

为了显示暗模式,我将暗模式类添加到 documentElement(html 标记)。在我的 CSS 中,我有第二组 CSS 规则集:

<style>
    body {
        background-color: #FFFFFF;
        font-family: 'Open Sans', sans-serif;
        color: #212121;
        font-weight: 400;
        line-height: 1.125em;
        height: 100%;
    }

    .dark-mode body {
        background-color: #121212;
        color:  #ffffff;
    }
</style>

切换颜色的另一个选项是在标签上应用 data-color-mode="dark" 属性并使用 CSS 变量:

:root {
  --background-color: #f0f0f0;
  --paragraph-color: #333;
}

[data-color-mode="dark"] {
  --background-color: #333;
  --paragraph-color: #ccc;
}

CSS 变量不适用于 Internet Explorer,因此它将恢复为 IE 的标准颜色。

因为我仍然需要支持 IE9 及更高版本,所以我不使用 CSS 变量选项,并且因为我使用基于 intersectionObserver 的延迟加载,我不给 IE 用户切换主题的选项——他们会自动获取浅色主题。

为了让它工作,我的头部有以下代码:

// IE doesn't get the dark mode option – I use IntersectionObserver as a proxy for IE
if ("IntersectionObserver" in window)  {
    window.dark = JSON.parse(window.localStorage.getItem("theme_mode"));
    if (window.dark === null) { // First time - use prefers color to set the theme
        if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
            window.dark = true;
            document.documentElement.className = document.documentElement.classList.add("dark-mode");
        } else {
            window.dark = false;
        }
        localStorage.setItem("theme_mode", JSON.stringify(window.dark));
    } else if (window.dark === true) { // Returning user - prefers dark
        document.documentElement.classList.add("dark-mode");
    } // Returning user - prefers light - window.dark is false
} else { // Browser is IE - hide dark mode stuff
    document.documentElement.classList.add(" ie");
}

IE9 不支持 classList,但如果访问者使用的是 IE9,我可以选择加载一个 polyfill。

要设置开关功能,我的页面底部有以下代码:

// set the selector switch to the right setting
var modeToggle = document.getElementById("light-dark-toggle");
if (window.dark) {
    modeToggle.checked = true;
} else {
    modeToggle.checked = false;
}

    
modeToggle.addEventListener('change', function() {
    window.dark = modeToggle.checked;
    if (window.dark) {
        document.documentElement.classList.add("dark-mode");
    } else {
        document.documentElement.classList.remove("dark-mode");
    }
    localStorage.setItem("theme_mode", JSON.stringify(window.dark));
    lazyLoad();
});

切换开关会导致页面重新加载图像,加载深色而不是浅色,反之亦然。

【讨论】:

    猜你喜欢
    • 2020-04-13
    • 2018-12-03
    • 2013-10-16
    • 1970-01-01
    • 2021-09-03
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    相关资源
    最近更新 更多