深色模式的六个层次(2024)

Hacker News Top 新闻

摘要

一篇探讨网页设计中深色模式实现的六个层次的文章,范围从基础的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指定每主题颜色的几种方法

Lobsters Hottest

本文介绍了五种仅用CSS实现每主题颜色(浅色/深色/自动)的技术,无需JavaScript,利用prefers-color-scheme、:has()、CSS变量和color-mix()等特性。

算法主题引擎

Hacker News Top

本文介绍了新的CSS `contrast-color()`函数,该函数允许开发人员自动选择黑色或白色文本,以实现与任何背景颜色的可访问对比度,解决网络上长期存在的低对比度问题,而无需依赖JavaScript。

readable.css

Lobsters Hottest

readable.css 是一个CSS框架,为网站提供了合理且美观的基础默认样式,支持亮/暗模式、响应式设计和垂直节奏,强调一致性和语义化HTML。

Ryanair 2026年夏季黑暗UX模式回顾

Hacker News Top

Dan O'Sullivan的博客文章幽默地剖析了Ryanair在2026年夏季结账过程中的黑暗UX模式,指出了用户在避免额外费用时必须经历的九个阶段,并提供了关于座位选择的实用技巧。

CSS:不可避免的坏部分

Lobsters Hottest

一位非Web开发者的个人博客文章讨论了CSS中不可避免的坏部分,包括布局难题、浏览器默认设置和过度使用包装器,同时强调了可处理简单任务的子集。