使用 color-scheme
CSS 属性和相应元标记改进深色模式默认样式
开发人员使用 color-scheme
CSS 属性和相应元标记可以选择其页面使用用户代理样式表的主题特定默认值。
背景 #
prefers-color-scheme
用户偏好媒体功能 #
开发人员使用 prefers-color-scheme
用户偏好媒体功能可以完全控制其页面的外观。如果您对它不熟悉,请阅读我的文章 prefers-color-scheme
:Hello darkness, my old friend(你好深色,我的老朋友),我在这篇文章里记录了我所知道的关于创造新颖深色模式体验的所有内容。
文章中只简单提到一个难题,便是 color-scheme
CSS 属性和同名称的相应 meta 标记。它们都允许您选择自己的页面使用用户代理样式表(例如表单控件、滚动条)的主题特定默认值,也可使用 CSS 系统颜色,从而使您的开发工作更轻松。同时,此功能还可防止浏览器自行应用转换。
用户代理样式表 #
在继续之前,我来先简要介绍一下什么是用户代理样式表。大多数情况下,您可以将用户代理 (UA) 一词视为浏览器的一种别致说法。UA 样式表决定了页面的默认观感。顾名思义,UA 样式表取决于相关 UA。您可以查看 Chrome(和 Chromium)的 UA 样式表,并与 Firefox 或 Safari(和 WebKit)的样式表进行比较。通常,UA 样式表在大多数方面都是一致的。例如,都将链接设置为蓝色,将一般文本设置为黑色,将背景颜色设置为白色,但也有重大(甚至有时令人烦恼)差异,例如,如何设置表单控件的样式。
仔细查看 WebKit 的 UA 样式表以及它对深色模式的作用。(在样式表中全文搜索 "dark"。)样式表提供的默认值会根据深色模式是打开还是关闭而发生变化。为了说明这一点,我们举个例子,一个 CSS 规则,使用 :matches
伪类和 WebKit 内部变量(例如 -apple-system-control-background
)以及 WebKit 内部预处理器指令 #if defined
:
input,
input:matches([type="password"], [type="search"]) {
-webkit-appearance: textfield;
#if defined(HAVE_OS_DARK_MODE_SUPPORT) &&
HAVE_OS_DARK_MODE_SUPPORT
color: text;
background-color: -apple-system-control-background;
#else
background-color: white;
#endif
/* snip */
}
您会注意到 color
和 background-color
属性的一些非标准值。text
和 -apple-system-control-background
都不是有效的 CSS 颜色,而是 WebKit 内部语义颜色。
事实证明,CSS 具有标准化语义系统颜色,在 CSS 颜色模块级别 4 中指定。例如,Canvas
(不要与 <canvas>
标记相混淆)用于应用程序内容或文档的背景,而 CanvasText
用于应用程序内容或文档中的文本。两者一起使用,不应单独使用。
UA 样式表可以使用自己的专有颜色或标准化语义系统颜色,来确定在默认情况下应如何呈现 HTML 元素。如果操作系统设置为深色模式或使用深色主题,则会将 CanvasText
(或 text
)有条件地设置为白色,并将 Canvas
(或 -apple-system-control-background
)设置为黑色。然后 UA 样式表仅分配以下 CSS 一次,并涵盖浅色和深色模式。
/**
Not actual UA stylesheet code.
For illustrative purposes only.
*/
body {
color: CanvasText;
background-color: Canvas
}
color-scheme
CSS 属性 #
CSS 颜色调整模块级别 1 规范引入了一个模型并通过用户代理控制自动颜色调整,目的是处理用户偏好(例如深色模式)、对比度调整或特定的所需配色方案。
通过其中定义的 color-scheme
属性,元素可以指示它适合渲染的颜色方案。将这些值与用户的偏好进行协调,从而生成影响用户界面 (UI) 事物的所选配色方案(例如表单控件和滚动条的默认颜色)以及 CSS 系统颜色的使用值。当前支持以下值:
normal
表示元素完全不知道配色方案,因此应该使用浏览器的默认配色方案呈现该元素。[light | dark]+
表示元素知道且可以处理列出的配色方案,并表达它们之间的排序偏好。
在此列表中,light
表示浅色方案:背景色浅,前景色深,而 dark
则相反:背景色深,前景色浅。
对于所有元素,使用配色方案渲染应使在所有浏览器提供的元素 UI 中使用的颜色与配色方案的意图相匹配。例如滚动条、拼写检查下划线、表单控件等。
在 :root
元素上,使用配色方案渲染还必会影响画布的表面颜色(即全局背景颜色)、color
属性的初始值以及系统颜色的使用值,并且还应影响视区的滚动条。
/*
The page supports both dark and light color schemes,
and the page author prefers dark.
*/
:root {
color-scheme: dark light;
}
color-scheme
meta 标记 #
提供 color-scheme
CSS 属性需要首先下载 CSS(如果此项通过 <link rel="stylesheet">
引用)并进行解析。为了帮助用户代理立即使用所需配色方案呈现页面背景,还可以提供 color-scheme
值(在 <meta name="color-scheme">
元素中)。
<!--
The page supports both dark and light color schemes,
and the page author prefers dark.
-->
<meta name="color-scheme" content="dark light">
color-scheme
和 prefers-color-scheme
相结合 #
由于 meta 标记和 CSS 属性(如果应用于 :root
元素)最终会产生相同的行为,我始终建议通过 meta 标记指定配色方案,这样浏览器可以更快地采用首选方案。
虽然绝对基线页面不需要额外的 CSS 规则,但在一般情况下,您仍应该始终将 color-scheme
与 prefers-color-scheme
结合起来。例如,专有 WebKit CSS 颜色 -webkit-link
(由 WebKit 和 Chrome 用于经典蓝色链接 rgb(0,0,238)
)在黑色背景上的对比度不足 2.23:1,并且不满足 WCAG AA 以及 WCAG AAA 要求。
我已经为 Chrome、WebKit 和 Firefox 以及 HTML 标准中的元问题报告了 Bug 以解决此问题。
与 prefers-color-scheme
相互影响 #
color-scheme
CSS 属性和相应 meta 标记与 prefers-color-scheme
用户首选项媒体功能的相互影响起初可能看起来令人困惑。但事实上,它们在一起配合得非常好。所要了解的最重要的事情是 color-scheme
专门确定默认外观,而 prefers-color-scheme
则确定可样式化的外观。为了更清楚地说明这一点,假设以下页面内容:
<head>
<meta name="color-scheme" content="dark light">
<style>
fieldset {
background-color: gainsboro;
}
@media (prefers-color-scheme: dark) {
fieldset {
background-color: darkslategray;
}
}
</style>
</head>
<body>
<p>
Lorem ipsum dolor sit amet, legere ancillae ne vis.
</p>
<form>
<fieldset>
<legend>Lorem ipsum</legend>
<button type="button">Lorem ipsum</button>
</fieldset>
</form>
</body>
页面上的内联 CSS 代码在一般情况下会将 <fieldset>
元素的 background-color
设置为 gainsboro
,也会将该值设置为 darkslategray
(如果用户优先选择 dark
,根据 prefers-color-scheme
用户偏好媒体功能)。
通过 <meta name="color-scheme" content="dark light">
元素,页面会告知浏览器它支持深色和浅色主题,且优先选择深色主题。
根据操作系统被设置为深色模式还是浅色模式,整个页面会基于用户代理样式表在深色中显示浅色,反之亦然。无需其他开发人员提供的 CSS 来更改页面的段落文本或背景颜色。
请注意,<fieldset>
元素的 background-color
根据是否启用深色模式而更改,遵循页面上开发人员提供的内联样式表中的规则。具体为 gainsboro
或 darkslategray
。

<fieldset>
元素的 background-color
为 gainsboro
。
<fieldset>
元素的 background-color
为 darkslategray
。<button>
元素的外观由用户代理样式表控制。它的 color
设置为 ButtonText
系统颜色,background-color
和四个 border-color
设置为系统颜色 ButtonFace
。

background-color
和各种 border-color
设置为 ButtonFace 系统颜色。现在,请注意 <button>
元素的 border-color
发生变化。计算值(针对 border-top-color
和 border-bottom-color
)从 rgba(0, 0, 0, 0.847)
(偏黑色)切换为 rgba(255, 255, 255, 0.847)
(偏白色),因为用户代理会根据配色方案动态更新 ButtonFace
。这同样适用于 <button>
元素的 color
,其设置为相应系统颜色 ButtonText
。

border-top-color
和 border-bottom-color
的计算值(在用户代理样式表中这两个值均设置为 ButtonFace
)现在为 rgba(0, 0, 0, 0.847)
。
border-top-color
和 border-bottom-color
的计算值(在用户代理样式表中这两个值均设置为 ButtonFace
)现在为 rgba(0, 0, 0, 0.847)
。演示 #
您可以看到应用于大量 HTML 元素 color-scheme
的效果(在故障演示中)。该演示特意显示 WCAG AA 和 WCAG AAA 冲突(具有上面警告中提到的链接颜色)。

color-scheme: light
。
color-scheme: dark
。请注意具有链接颜色的 WCAG AA 和 WCAG AAA 冲突。鸣谢 #
color-scheme
CSS 属性和相应 meta 标记由 Rune Lillesveen 实施。Rune 也是 CSS 颜色调整模块级别 1 规范的共同编辑者。主图作者:Philippe Leone 来源:Unsplash。