css未来:使用light-dark()切换主题色
要根据使用的是浅色模式还是深色模式来更改颜色,我们通常会使用 prefers-color-scheme 媒体查询。为了让代码实现变得更容易,CSS 现在附带了一个名为 light-dark() 的实用函数。该函数接受两个颜色值作为其参数。根据我们正在使用的配色方案,它将使用第一个或第二个参数。
使用 prefers-color-scheme 切换主题色
要根据所使用的浅色模式或深色模式更改颜色值(或任何其他值),我们通常会使用媒体prefers-color-scheme 查询来更改自定义属性的值:
css
:root {
--text-color: #333; /* 浅色主题色 */
}
@media (prefers-color-scheme: dark) {
:root {
--text-color: #ccc; /* 深色主题色 */
}
}
实现深色模式时,通常会得到一堆重复的 CSS 变量,这些变量为每种模式设置值。然后,CSS 的其余部分将这些自定义属性用于实际声明。
css
body {
color: var(--text-color);
}
使用 light-dark() 切换主题色
CSS 颜色模块第 5 级规范 的新增功能是 light-dark() 功能。该函数接受两个颜色值作为其参数。根据我们正在使用的颜色方案,它将使用第一个或第二个颜色参数。
css
light-dark(<color>, <color>);
根据规格:
如果使用的配色方案为 light 或未知,则此函数计算第一种颜色的计算值;如果使用的配色方案为dark,则此函数计算第二个颜色的计算值。
使用的配色方案不仅基于用户的浅色/深色模式设置,还基于属性的值 color-scheme。这类似于系统颜色的计算方式。
color-scheme属性允许元素指示其设计用于渲染的配色方案。这些值是根据用户的偏好进行协商的,从而产生使用的配色方案。
这意味着,为了 light-dark() 起作用,我们还必须包含一份 color-scheme 声明。
css
:root {
color-scheme: light dark;
}
:root {
--text-color: light-dark(#333, #ccc); /* 在浅色模式使用#333,在深色模式使用#ccc */
}
因为 color-scheme 的声明方式,这也意味着我们可以覆盖每个元素的值,以强制其进入某种模式:
css
.dark {
color-scheme: dark; /* 在.dark元素上使用 light-dark,.dark元素的所有子元素都是深色模式 */
}
light-dark()看起来跟Chromium 内部的 -internal-light-dark()很类似。基于此功能, CSS 工作组内提出了向作者公开类似功能的提案。结果就诞生了 light-dark()。
-internal-light-dark() 适用于任何类型的值,而 light-dark() 只能用于颜色。
其他非颜色值能否支持
light-dark() 的功能相当有限:它只能处理 light/dark,并且只能处理值。这是正确的,也是非常有意的,因为这是迈向最终解决方案的中间步骤。
正如CSS 工作组问题中所提出的,最终目标是在未来(暂定)有一个命名的函数。该函数功能可以:
- 响应 color-scheme 的任意值。
- 返回的不仅仅是 值
它可能看起来像这样:
css
:root {
color-scheme: dark light custom;
}
body {
color: schemed-value(light hotpink, dark lime, custom rebeccapurple);
}
但是,就目前而言,我们"仅"拥有 light-dark(),而且我个人认为这很好,因为它与当今浏览器可以执行的操作的现实相符:
- 它只支持 light/dark 。因为浏览器现在不支持incolor-scheme,所以现在支持其他值是没有用的。
- 它只能处理值,因为解析器需要提前知道它正在解析的值的类型。light-dark()被明确定义为一个值。
light-dark() 的名称和语法非常容易记住,易于使用。
当 schemed-value() 成为一个事物时,light-dark()就会成为它的语法糖:
csslight-dark(<color>, <color>); = schemed-value(light <color>, dark <color>);
浏览器支持
目前只有 firefox 支持,如果我们想体验这个功能,可以使用firefox进行测试。