大家好,这里是大家的林语冰。
免责声明
本文属于是语冰的直男翻译了属于是,仅供粉丝参考,英文原味版请临幸 The Future of CSS: Easy Light-Dark Mode Color Switching with light-dark()。
引言
为了基于 Light/Dark Mode(亮暗模式)改变颜色,您通常会诉诸 prefers-color-scheme
媒体查询。为了简化这种需求,CSS 现在天降了一个 light-dark()
实用函数。该函数接受两个颜色值作为其参数。根据您激活的配色方案,它会输出第一或第二个参数。
响应亮暗模式
为了基于亮暗模式来改变颜色(或其他值),您通常会诉诸 prefers-color-scheme
媒体查询来改变自定义属性的值。
css
:root {
--text-color: #333; /* Value for Light Mode */
}
@media (prefers-color-scheme: dark) {
--text-color: #ccc; /* Value for Dark Mode */
}
在 实现暗模式 时,您通常会得到一大坨重复的 CSS 变量,这些变量为每种模式设置值。CSS 的其余部分使用这些自定义属性进行实际声明。
css
body {
color: var(--text-color);
}
诉诸 light-dark() 响应亮暗模式
CSS 颜色模块 Level 5 规范 新增了 light-dark()
函数。该函数接受两个颜色值作为其参数。根据您激活的配色方案,它会输出第一或第二个颜色参数。
css
light-dark(<color>, <color>);
根据 per 规范:
若使用的配色方案是
light
或未知,则该函数计算第一种颜色的计算值;若使用的配色方案是dark
,则该函数计算第二种颜色的计算值。
使用的配色方案不仅基于用户的"亮暗模式"设置,还基于 color-scheme
属性的值。这类似于 系统颜色 的计算方式。
color-scheme
属性允许一个元素指定它被设计为渲染特定的配色方案。这些值与用户的偏好协商,从而产生所使用的配色方案。
这意味着,要让 light-dark()
奏效,您还必须设置一个 color-scheme
声明。
css
:root {
color-scheme: light dark;
}
:root {
--text-color: light-dark(
#333,
#ccc
); /* In Light Mode = return 1st value. In Dark Mode = return 2nd value. */
}
因为考虑了 color-scheme
,这也意味着您可以覆盖每个元素的对应值,强制它进入某种模式:
css
.dark {
color-scheme: dark; /* light-dark() on this element and its children will always return dark */
}
如果这个
light-dark()
似曾相识:Chromium 内部有一个 我以前写过的-internal-light-dark()
。基于此功能,CSS 工作组制定了向作者暴露一个类似函数的 提案。结果就是light-dark()
。
与 -internal-light-dark()
用于任何类型的值不同,light-dark()
能且仅能用于颜色。
关于其他 non-<color>
的值和响应其他配色方案
关于 light-dark()
,我得到的一种常见反馈是,它能干的事相当有限:它能且仅能搞亮暗模式,而且能且仅能和 <color>
值一起使用。言之有理,但这正是其设计意图,因为这是走向最终解决方案的必由之路。
正如 CSS 工作组 issue 的建议,最终目标(暂时)是在未来拥有一个名为 schemed-value()
的函数。该函数可以:
- 响应
color-scheme
的任何值。 - 返回包括但不限于
<color>
值等。
它可能看起来像这样:
css
:root {
color-scheme: dark light custom;
}
body {
color: schemed-value(
light hotpink,
dark lime,
custom rebeccapurple
);
}
虽然但是,就目前而言,我们"有且仅有" light-dark()
,私以为这很 OK,因为它符合今天浏览器实际可以做的事情:
- 它只支持
light
或dark
,因为浏览器目前 不支持<custom-ident>
和color-scheme
,所以现在支持其他值是无用功。 - 它只能处理
<color>
值,因为 解析器需要提前知道它解析的值的类型。light-dark()
被明确定义为<color>
。
缩小功能范围(从非常广泛的 schemed-value()
到精简的 light-dark()
) ------ 允许函数按照目前这样定义,而不是将整个事情规划到猴年马月。
light-dark()
的名称和语法非常好记,易于使用,最重要的是,它为作者今天使用的常见用例提供了解决方案。
粉丝福利
当
schemed-value()
尘埃落定,light-dark()
将成为它的语法糖:
css
light-dark(<color>, <color>);
/* 等价于 */
schemed-value(light <color>, dark <color>);
浏览器支持
粉丝福利
虽然这篇文章最初发表于 2023 年 10 月,但下面章节会持续更新。上次更新时间:2023 年 10 月 9 日。
以下是浏览器支持 CSS light-dark()
的最新列表:
浏览器(内核) | 兼容性 |
---|---|
Chromium (Blink) | ❌ 暂不支持 |
Firefox (Gecko) | ✅ Firefox@120 开始支持 |
Safari (WebKit) | ❌ 暂不支持 |
(如果你想知道这还没有出现在 CanIUse(浏览器兼容性相关网站)上的原因:这个功能是最新的。添加数据的 PR 仍处于待定状态。)
这个 在线代码示例 会测评你当前使用的浏览器是否支持 CSS light-dark()
。
如果想了解浏览器支持的最新资讯,您可以关注以下跟踪 issue:
- Chromium/Blink: Issue #1490618 ------ 已分配(开启状态)
- Firefox/Gecko: Issue #1856999 ------ 完成状态(已修复)
- Safari/WebKit: Issue #262914 ------ 新开状态
代码示例
如果你的浏览器支持 light-dark()
,下面的示例会显示若干标记为 .auto
的 <div>
,它们响应亮暗模式的切换。具有 .light
或 .dark
类选择器的 <div>
会强制切换为正确的亮暗模式。
学废了的小伙伴可以点赞给语冰打 call,欢迎关注最新动态和订阅前沿资讯。谢谢大家的彼芯,掰掰~