zzxworld

用 CSS 实现可切换的明暗样式功能

博客作为以文字为类型的内容媒介,提升阅读体验是一项永无止境的工作。今天就来分享一个与之相关的优化事项:通过 CSS 来实现明暗样式的功能支持。

使用这个优化项的缘由是目前各大操作系统都已经支持的「Light」和「Dark」模式。比如我目前使用的 Gnome 桌面环境,在系统的主题样式设置中,就有这样的选项:

gnome-appearance-ui

Windows 和 macOS 系统也有类似的配置。至于手机系统,就更不必说了。

用户通过选择系统的 「Light」和「Dark」模式可以调整自己的使用舒适度。而让自己的网站顺应系统的显示模式,自然也更契合用户的意愿和选择。

媒体查询

完成这件事情的第一步,是让 Web 应用感知系统当前所处的模式。这需要借助 CSS 提供的 「媒体查询」功能。

通过 prefers-color-scheme 这个媒体查询参数,可以轻松获知当前系统的样式选择。来看一个简单例子:

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>Dark/Light Demo</title>
<style type="text/css">
    body {
        background: #FFF;
    }

    h1 {
        color: #000;
    }

    @media (prefers-color-scheme: dark) {
        body {
            background: #000;
        }

        h1 {
            color: #FFF;
        }
    }
</style>
</head>
<body>
    <h1>zzxworld</h1>
</body>
</html>

把以上代码保存为一个 HTML 文件,然后在浏览器打开。当调整系统的明暗选项时,会发现这个页面的背景和文字颜色会自动改变。

demo-in-light.png 使用亮色主题时的显示效果

demo-in-dark.png 使用暗色主题时的显示效果

自定义属性

通过上面的例子可以发现,通过 CSS 实现明暗样式的支持非常简单。简单来说就是准备两套显示方案,然后根据 prefers-color-scheme 这个媒体查询参数来完成应用就可以了。不过在稍微复杂的 CSS 样式环境下,这些跟颜色相关的显示方案维护起来会是个问题。为解决这个问题,引入 CSS 的「自定义属性」特性会是一个不错的解决方案。

还是上面的例子,引入 CSS 自定义属性后的代码如下:

<html lang="zh">
<head>
<meta charset="utf-8">
<title>Dark/Light Demo</title>
<style type="text/css">
    :root {
      --bg-color: #FFF;
      --text-color: #000;
    }

    @media (prefers-color-scheme: dark) {
        :root {
            --bg-color: #000;
            --text-color: #FFF;
        }
    }

    body {
        background: var(--bg-color);
    }

    h1 {
        color: var(--text-color);
    }
</style>
</head>
<body>
    <h1>zzxworld</h1>
</body>
</html>

代码看起来变多了,不过对比一下其中的差异就会发现,引入 CSS 自定义属性后,涉及明暗样式的 CSS 代码就可以抽象出来单独管理了。这对后期的维护和调整会带来不少便利。


最后作为提示需要注意,以上用到的 CSS 特性 IE 均不支持。