MENU

如何使网页自动适配 Mac 的 Dark Mode

• March 15, 2019 • Read: 237 • Codes

前段时间 Safari Technology Preview 中添加了对媒体查询 prefers-color-scheme 的支持,该特性可以帮助我们适配 Mac 中的 Dark Mode(深色模式)。虽然目前 Mojave 10.14.3 版本的 Safari 中尚未添加该特性,但其将随着 Safari 12 在下个小版本(macOS 10.14.4, 10.13.6 and 10.12.6)更新中获得支持。

prefers-color-scheme 可以检测到用户是否已请求操作系统使用浅色或深色主题,其有三个可选的选项:

  • no-preference:未能检测到用户的选择
  • light:用户倾向于使用浅色的主题
  • dark:用户倾向于使用深色的主题,例如用户开启了 Mac 中的深色模式

所以,在这里我们可以使用 prefers-color-scheme: dark 来检测用户是否开启了 Dark Mode。

开始使用

prefers-color-scheme 的使用很简单,和普通的 Media Query 一样:

/* 操作系统及浏览器未支持或用户未开启 Dark Mode */
body {
    backgound-color: white;
    color: black;
}

@media (prefers-color-scheme: dark) {
    /* 操作系统及浏览器支持且用户开启了 Dark Mode */
    body {
        backgound-color: black;
        color: white;
    }
}

这样,用户在平时看到的是白色背景,而开启了深色模式后,页面就会自动变为黑色背景。当然,夜间模式的适配需要做的工作还很多,需要你慢慢调整各元素的颜色等。

顺便说一下,目前版本中,如果使用 @supports (prefers-color-scheme: dark) 包裹上述 Media Query 代码,则可能不会生效,这个看上去应该是目前版本浏览器的 Bug。

通过 JavaScript 获取是否开启了深色模式 Dark Mode

很多网站已经有了夜间模式,使用 prefers-color-scheme 适配可能比较麻烦,那么可以使用 JS 获取用户是否开启了 Dark Mode (深色模式),然后按照旧的逻辑开启夜间模式。

这种模式有个缺点:无法像直接使用 Media Query 的情况一样,在用户开启深色模式的时候,已打开的浏览器页面会自动变为深色模式,只有刷新页面或新进入的用户才会使用深色模式,不过个人感觉体验上影响不大。

当然,JS Api 是没有的,这里只能通过迂回的方式通过 JS 获取。

添加 CSS 属性

.dark-mode-state-indicator {
    position: absolute;
    top: -999em;
    left: -999em;

    z-index: 1;
}

@media (prefers-color-scheme: dark) {
    .dark-mode-state-indicator {
        z-index: 11;
    }
}

添加 JS 代码

var getDeviceState = function(element) {
    var zIndex;

    if (window.getComputedStyle) {
        // 现代浏览器
        zIndex = window.getComputedStyle(element).getPropertyValue('z-index');
    } else if (element.currentStyle) {
        // ie8-
        zIndex = element.currentStyle['z-index'];
    }

    return parseInt(zIndex, 10);
}

var getPrefersDarkModeState = function () {
    var indicator = document.createElement('div');
    indicator.className = 'dark-mode-state-indicator';
    document.body.appendChild(indicator);
    return getDeviceState(indicator) === 11;
    // 根据情况在获取完后删除该 div
};

使用的时候调用 getPrefersDarkModeState() 方法就可以了。

考虑到最后的效果,可能不建议将上述代码放到页面底部的 JS 文件中。

参考

最后编辑于: March 20, 2019
Archives QR Code Tip
QR Code for this page
Tipping QR Code
Leave a Comment

已有 9 条评论
  1. 干得漂亮
    可惜快活哥我没有MAC

  2. 这两天正想给主题加上夜间模式,看来能用上这个。老哥超棒!#(赞一个)

    1. @熊猫小A::quyin:1huaji::

  3. 还是老哥的夜间模式比较全面些::quyin:1huaji::

  4. 棒啊老哥,开始高产了::quyin:1huaji::

    1. @左岸高产似母猪,寿命:两天::quyin:1huaji::

  5. 这个头图的比例也太bling了~

    1. @JinF头图比例?啥意思啊#(狂汗)

    2. @Hran夸你头图 bling bling呢::quyin:1huaji::