深色模式的六个层次(2024)
摘要
一篇探讨网页设计中深色模式实现的六个层次的文章,范围从基础的meta标签方法到使用CSS的高级配色方案切换技术。
暂无内容
查看缓存全文
缓存时间: 2026/04/20 14:44
# 深色模式的六个层次 来源:https://cssence.com/2024/six-levels-of-dark-mode/
1. 极简 (https://cssence.com/2024/six-levels-of-dark-mode/#level-1-barebone)
2. 基础 (https://cssence.com/2024/six-levels-of-dark-mode/#level-2-basic)
3. 温和 (https://cssence.com/2024/six-levels-of-dark-mode/#level-3-benign)
4. 大胆 (https://cssence.com/2024/six-levels-of-dark-mode/#level-4-bold)
5. 分割 (https://cssence.com/2024/six-levels-of-dark-mode/#level-5-bisectional)
6. 激进 (https://cssence.com/2024/six-levels-of-dark-mode/#level-6-ballistic)
7. --- 超越 (https://cssence.com/2024/six-levels-of-dark-mode/#level-7-beyond)
8. 诱人 (https://cssence.com/2024/six-levels-of-dark-mode/#level-8-beguiling)
今年 CSS Naked Day 期间,我不仅再次想到了“视觉上隐藏”的讨论 (https://cssence.com/2024/native-visually-hidden/),还注意到:访问的几乎所有网站在去掉了样式之后,深色模式几乎都消失了。这让我思考,也许现在是时候聊聊 **深色模式的六个层次** 了。
这篇博文如果取个没那么 catchy 但更准确的标题,应该是“配色切换的六个层次”。不过算了。本文示例代码大多展示的是 *暗色面*,所以标题也算合理。只需记住,反过来也一样适用。话不多说,开始吧。
## 第1层:极简 (Barebone)
这一层最简单不过了,但显然引言中提到的那些网站缺少了最基本的指令。即使没有一行 CSS,你也可以启用浅色/深色模式切换,这在平时很棒,在 4月9日 (https://cssence.com/about/css-naked-day/) 尤其如此。只需在文档 head 中添加以下 meta 标签,一切就绪。
```html
<meta name="color-scheme" content="light dark" />
```
只要网页包含这个标签,浏览器就知道它应该遵循用户对配色方案的偏好。`content` 属性中条目的顺序在理论上是有意义的:没有偏好的用户会得到列表中第一个(空格分隔的值)。但今天操作系统的设置中并没有“不选择”的选项,所以你最终总是会得到与操作系统匹配的那一个。如果你在 content 属性中只指定一个条目,那么就会强制使用对应的方案,而不考虑用户偏好——但那是另一个故事了。
在某种程度上,这个 meta 标签相当于我们下一个层次的 HTML 等效物。
## 第2层:基础 (Basic)
让我们进入使用 CSS 来实现浅色/深色模式切换的方式。
```css
html {
color-scheme: light dark;
}
```
如果你已经在 DOM 中添加了 meta 标签,就不需要这个声明了。除非你无法控制 HTML(例如内容来自 CMS,那你真惨),我建议你始终使用 meta 标签。这给了浏览器一个**优势**:在解析任何 CSS 之前,它就知道了配色方案指令。两种方式本质上都让你可以借助用户代理的默认样式,以及随之而来的浅色/深色模式。
现在添加一些 CSS,但或许可以限制自己只使用 CSS 系统颜色 (https://developer.mozilla.org/en-US/docs/Web/CSS/system-color),这样你就能实现相当简洁的设计了。嘿,本站的页面样式切换器 (https://cssence.com/settings/#page-style) 有“无(None)”和“基础(Basic)”两个选项,对应第1层和第2层。
这就引出了两者的不同之处。与始终适用于整个文档的 meta 标签不同,CSS `color-scheme` 声明可以设置在任意位置,而不仅仅是根元素上。这带来了一些额外的使用场景,但我将在另一篇博文中讨论 (https://cssence.com/2025/nesting-color-schemes/)。
## 第3层:温和 (Benign)
我们已经过了基础阶段,但仍在浅水区。CSS 中一个较新的功能——`light-dark()` 颜色函数——允许简单的浅色/深色模式调整。
```css
html {
background-color: light-dark(black, white);
color: light-dark(white, black);
}
```
该函数接受两个参数,都应该为颜色值。第一个在浅色模式下应用,第二个的作用你大概猜得到。你可以直接指定具体颜色,或者使用解析为颜色的自定义属性。这是本文中唯一一个目前浏览器支持不太好的层级 (https://caniuse.com/mdn-css_types_color_light-dark),但我们会解决这个问题。
## 第4层:大胆 (Bold)
接下来是经典的媒体查询。
```css
@media (prefers-color-scheme: dark) {
html {
background-color: black;
color: white;
}
}
```
无论你查询的是 `light` 还是 `dark`,媒体查询都允许最大程度的自定义,因为你不仅限于更改颜色。什么都可以放进去。想在深色模式下用滤镜让图片去饱和?请便。用轮廓线替换盒子阴影?当然可以。
## 第5层:分割 (Bisectional)
你也可以在 HTML 中使用媒体查询。将其作为 `media` 属性,可以为每种方案创建独立的样式表。
```html
<link rel="stylesheet" href="light.css" media="screen and (prefers-color-scheme: light)" />
<link rel="stylesheet" href="dark.css" media="screen and (prefers-color-scheme: dark)" />
```
如果你要做大量自定义,专用文件就很有意义。浏览器可能会忽略任何与查询不匹配的 CSS 文件,这样就少下载一个文件。
## 第6层:激进 (Ballistic)
显然 JavaScript 也想参与其中。你可以使用 `matchMedia` 函数来查询浅色或深色方案,就像其他媒体查询一样。
```js
const isDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
```
然后做任何你想做的事。
---
在现实中,你并不会只停留在某一条路线上,而是可以混合搭配前面所有层级的技术。
## 第7层:超越 (Beyond)
你不必完全依赖用户偏好,可以构建一个 **配色方案切换器**。如果这么做,要小心:浅色或深色模式的偏好并不是一个布尔状态,因为最初你希望默认是“自动(Automatic)”,即遵循 `prefers-color-scheme`。通过在此基础上构建方案切换器 (https://cssence.com/settings/#color-scheme),你可以让用户选择三种模式之一。
一个配色方案切换器;其下拉菜单显示“自动(默认)”、“深色”和“浅色”选项。
如果你已经知道了以上所有内容,我还有最后一层要介绍。
## 第8层:诱人 (Beguiling)
当 Web 开发者创建第7层的 **配色方案切换器** 时,他们通常会给 HTML 元素添加一个类似 `.dark` 的类,有时甚至是一个花哨的 `data-theme="dark"` 属性。但我们不再需要这些了,因为我们可以使用 `:has()` 来直接查询真实状态。
```css
html:has(meta[name="color-scheme"][content="dark"]) {
--color-bg: black;
--color-text: white;
}
```
请查阅我的配套文章《配色方案切换器,2024版》(https://cssence.com/2024/color-scheme-switcher/) 查看实际效果。
我确实又看到了几个网站把这用在了 `<head>` 里!不过同意,最近 CSS 提供的功能太强大了。从头开始一个带新样式的网站时,现在很容易就能把浅色和深色模式融入进去。🙂
回复 @[email protected]: 很高兴听到这一点。另外,似乎我们访问的网站不太一样。😅 CSS Naked Day 的 Webring 有意义吗?🤔
回复 @[email protected]: 这似乎只针对裸体日有点太具体了……哦,除非是带导航栏和 iframe 之类的!老派……
回复 @[email protected]: 框架集?不,等等,那可能会适得其反……adactio.com/journal/17916 (https://adactio.com/journal/17916)
回复 @[email protected]: CSS 裸体环?太棒了!我加入!它可以是一个普通的环,但带有一个 URL 参数表示需要“裸体”吗?可能也适用于 JS 裸体日 @[email protected]。顺便说一句,我相当肯定我的网站在裸体日期间正确地支持了深色/浅色偏好。😉
回复 @[email protected]: > 深色和浅色配色方案偏好仍然被尊重。看起来是的。😀👍 干得好!
加上很多混合层级。用颜色变换 JS 变量,隐藏的自动配色方案:gist.github.com/iamdtms/ddc4e556805e60652c21c06281d5b3c2 (https://gist.github.com/iamdtms/ddc4e556805e60652c21c06281d5b3c2)
有一点需要注意的是,直到最近(也许是最新版本),Safari 的深色模式中没有可访问的链接颜色。在去年的 CSS Naked Day 期间,我在自己的网站上注意到了这个问题,于是决定去掉 meta 标签,只使用浅色配色方案。今年,虽然我知道这可能会给使用旧版 Safari 的用户带来不便,但我还是加回了 meta 标签。我确实注意到文本框在 Safari 深色模式下没有可见的边框。我开始觉得,将来我可能需要在 CSS Naked Day 中加入足够的样式来保持网站的可访问性,因为用户代理样式并非完全可访问(即使有了正确、语义化的 HTML)。
回复 @[email protected]: 是的,好观点。不过话说回来,如果你放眼望去,发现全年有多少网站在无障碍方面都做得不行,那么4月9日可能只是我们最不用担心的小事了。
回复 @[email protected], @[email protected]: 我几乎觉得在那一天看到无障碍失败也是这件事的一部分。但你努力为所有人保持良好体验是件好事。
我很好奇为什么在“分割”示例中使用了 `screen and ...`。默认(没有前缀时)会是 `all and ...`,效果相同,除非你想对打印机隐藏样式。
回复 @[email protected]: 是的,对打印机隐藏样式正是这样想的,我认为打印样式要么在主题无关的核心样式表中处理,要么在专用的打印样式表中处理。所以我想确保安全,为打印机启用深色模式可能会浪费很多墨水。😉
回复 @[email protected]: 我切换了系统深色模式,并用默认的深色模式样式(通过 color-scheme 启用)打印了一个示例页面。我甚至尝试启用了“背景图形”选项。结果墨水全都显示在白色纸上。似乎所有浏览器都不会把它们应用到打印中。
回复 @[email protected]: 有意思。我也做了个测试:打开我的媒体查询测试页面 (https://cssence.com/2024/media-queries-including-level-5/),在打印预览中 `prefers-color-scheme` 总是报告 `light`。这很合理。我想这也是你得到那个结果的原因。好消息。😀👍(我只测试了 Firefox 和 Chromium。)
回复 @[email protected]: 不过,如果你有黑色纸张和白色墨水,那就糟糕了,你知道的。😄
回复 @[email protected]: 🤣
回复 @[email protected], @[email protected]: 深色模式打印机!
### 参与讨论
在 Mastodon (https://mas.to/@CSSence/112281217350850297) 上发表你的看法,或者直接[分享本文](mailto:?subject=Six%20levels%20of%20dark%20mode%20-%20CSSence.com&body=https%3A%2F%2Fcssence.com%2F2024%2Fsix-levels-of-dark-mode%2F)。
相似文章
仅用CSS指定每主题颜色的几种方法
本文介绍了五种仅用CSS实现每主题颜色(浅色/深色/自动)的技术,无需JavaScript,利用prefers-color-scheme、:has()、CSS变量和color-mix()等特性。
算法主题引擎
本文介绍了新的CSS `contrast-color()`函数,该函数允许开发人员自动选择黑色或白色文本,以实现与任何背景颜色的可访问对比度,解决网络上长期存在的低对比度问题,而无需依赖JavaScript。
readable.css
readable.css 是一个CSS框架,为网站提供了合理且美观的基础默认样式,支持亮/暗模式、响应式设计和垂直节奏,强调一致性和语义化HTML。
Ryanair 2026年夏季黑暗UX模式回顾
Dan O'Sullivan的博客文章幽默地剖析了Ryanair在2026年夏季结账过程中的黑暗UX模式,指出了用户在避免额外费用时必须经历的九个阶段,并提供了关于座位选择的实用技巧。
CSS:不可避免的坏部分
一位非Web开发者的个人博客文章讨论了CSS中不可避免的坏部分,包括布局难题、浏览器默认设置和过度使用包装器,同时强调了可处理简单任务的子集。