CSS亮黑主题切换
撰写时间:2025-03-03
修订时间:2025-12-18
无任何CSS设定的输出
下面结果面板中的内容无任何CSS设置。
This is some sample paragraph texts.
因为没有任何CSS设置,因此结果面板默认情况是白底黑字。在系统中切换颜色模式,结果面板中不会有任何变化。
color-scheme
自动设置主题颜色
This is some sample paragraph texts.
点击Run
按钮,当设置了color-scheme属性值后,在系统中切换颜色主题,则结果面板的内容能自动响应系统的颜色模式切换。
这一点也说明了Web Components下面的各个子标签(被ShadowRoot所隔离),也能接收到系统发来的信息。
我们在根目录下设置了color-scheme,则根目录下所有的子标签,都能响应主题颜色变换。当模式为light
时,所有子标签自动变成白底黑字;当模式为dark
时,所有子标签自动变成黑底白字。
只设置亮色主题颜色
可以只选择一种颜色模式。
This is some sample paragraph texts.
上面设置,则不管系统的主题颜色是什么,都只会自动使用light
模式的设置,即自动设置为白底黑字。
只设置暗色主题颜色
下面只使用dark
模式。
This is some sample paragraph texts.
分别设置主题颜色
根据规范,可以为各个子标签分别设置不同的主题颜色。
This is paragraph 1.
This is paragraph 2.
但Chrome及Safari目前只支持在:root标签中设置color-schme,从而使这种技术形同虚设。
用户设置优先
This is paragraph 1.
This is paragraph 2.
有2个p,第1个p设置了灰底橙字,则用户设置优先,不管系统的主题颜色是什么,p1永远都是灰底橙字。而p2未进行任何自定义设置,则仍由浏览器根据系统主题颜色来自动设置样式。
也即说,使用color-scheme,一旦我们自行设定,浏览器就不再接管。
prefers-color-scheme
使用媒介查询技术中的prefers-color-scheme,网页内容照样可以收到系统主题颜色变换的信息,并且可以只针对亮色主题或暗黑主题进行单独的设置。
This is paragraph 1.
This is paragraph 2.
这样,当系统发来当前颜色主题的信息时,分别调用相应的设置值,从而在网页中较为智能地实现了颜色主题的切换。
prefers-color-scheme可以配合color-scheme同时使用。
This is paragraph 1.
This is paragraph 2.
在prefers-color-scheme的设置中,只对p1进行了设置。由于p2未设置,则由color-scheme为其自动设置。
但由于CSS属性值具有继承性,我们一般在父标签上设置一个通用值而由子元素自动继承,因此这种同时设置上述两个CSS属性值的场合并不多见。
light-dark()函数
使用prefers-color-scheme最大的问题,是我们必须同时为亮色与暗黑主题分别设置不同的值,并且,同一标签在亮色与暗黑主题的不同的值,散列于不同的代码块中,在维护时,当需要修改某个标签的值时,得在两个代码惨块中同时修改。因此,代码量不仅成倍增长,维护更为不便。
CSS Color Module Level 5草案引入了light-dark函数,提供了更为简洁的颜色主题适配方案。
This is paragraph 1.
This is paragraph 2.
light-dark函数必须配合color-scheme来使用,后者用以接收从系统传来的颜色主题切换消息。
这样,代码简洁了不少,且由于相关设置值都集中置于特定标签后面,维护起来非常方便。从这点上来讲,它在一定程度上消除了大量使用CSS变量的必要性。
Chrome支持,Safari 18.2默认打开了light-dark函数的功能开关。因此,均可放心使用。
许多网站目前仍使用以下格式来编写CSS代码:
This is paragraph 1.
This is paragraph 2.
这些网站会自动将body的父元素html的class属性值设置为light或dark,以便让上述CSS生效。
其缺点是,为body设置颜色的代码明显分成两小块,维护困难。对于这种代码,在尊重其原有DOM结构的基础上,我们也可改写为Nested CSS的形式:
This is paragraph 1.
This is paragraph 2.
这种效果类似于使用light-dark函数,特定元素的所有设置颜色的代码均置于该元素的选择器之下,维护很方便。
matchMedia
除了CSS设置外,我们还可在JavaScript中调用window.matchMedia方法来查询在CSS是否已设置特定的系统颜色主题响应。
Toggle color scheme in system to change the color scheme in HTML page.
matchMedia返回一个MediaQueryList对象,其media属性值为我们所要查询的字符串,如果已设置,则matches属性值为true,否则为false。
可以为MediaQueryList对象设置onchange响应事件,这样,当系统颜色主题发生改变时,我们可进一步响应此事件。但一般情况下,当我们在CSS设置了:
之后,当系统颜色主题发生改变时,浏览器将自动先行收到消息并应用我们已经设置好的相应的颜色,然后再响应MediaQueryList的onchange事件,因此我们应尽可能将自动改变颜色的代码放在CSS的light-dark函数中,这样既便捷且易维护。只有在我们需要相对比较复杂的业务逻辑判断时,才需要自行响应其onchange事件。
上面的代码,如果没有设置onchange事件,已经可以自动响应系统颜色主题的切换而改变颜色。在该事件中,我们只是简单地打印出当前颜色主题而已。
允许用户指定颜色主题
以上,当我们在系统中选定了颜色主题后,相应主题的CSS样式将自动被调用。
但我们应当允许用户指定颜色主题,以覆盖系统当前颜色主题。
主要有2种方法可实现此目标。第一种是当我们收到系统颜色主题变更通知时,为html或body标签的class设置相应的light
或dark
值,然后,为它们的各个子标签分别进行相应的颜色设置:
但更简便的方法是,通过JavaScript直接修改color-scheme的值即可。
当我们允许用户可自行选择颜色主题时,又分为两种情况。第一种情况,允许用户选择根据系统颜色主题来自动切换网页颜色;第二种情况,不管系统是什么颜色主题,完全由用户自行决定亮色或暗色。下面代码反映了这两种情况。
Hello, color scheme.
使用第二种方式,配合CSS的light-dark函数,两套颜色主题的代码完全集中于一处,代码维护非常方便。
一个完整的例子
综合应用上述各节的技术,本站使用iframe编写了一个完整且可独立运行的例子,具体详见在 iframe 中玩转 Color Scheme。
