快速了解 CSS light-dark 函数及其应用

开发 前端
白天和黑夜模式比较好实现,是固定的,这里直接用:has配合:checked来动态匹配当前选中项,然后改变CSS变量就行了。实际项目中,如果考虑兼容性,可以用 JS 动态切换 class 来匹配。

介绍一个和主题密切相关的CSS特性:light-dark,有了它,可以更灵活的适配各种主题模式。

一、prefers-color-scheme

一般来讲,网站会有三种主题模式,白天、黑夜、自动跟随系统,比如下面的 MDN 官网。

前面两者是固定的,不会跟随系统变化。

这里简单实现一下三种主题模式,假设有这样一个结构。

<body>
  <h1>前端侦探</h1>
</body>

我们用input radio来实现切换效果。

<body>
  <fieldset>
    <input type="radio" name="theme" value="light" id="light" checked><label for="light">白天</label>
    <input type="radio" name="theme" value="dark"  id="dark"><label for="dark">黑夜</label>
    <input type="radio" name="theme" value="auto"  id="auto"><label for="auto">自动</label>
  </fieldset>
  <h1>前端侦探</h1>
</body>

简单修饰一下,效果是这样的。

通常我们会用 CSS变量来动态改变主题色,这里简单一点,就用文字颜色和背景来表示。

:root{
  --bg: aliceblue;
  --color: #000;
}

白天和黑夜模式比较好实现,是固定的,这里直接用:has配合:checked来动态匹配当前选中项,然后改变CSS变量就行了。

实际项目中,如果考虑兼容性,可以用 JS 动态切换 class 来匹配。

:has(#light:checked){
  body{
    --bg: aliceblue;
    --color: #000;
  }
}
:has(#dark:checked){
  body{
    --bg: #000;
    --color: #fff;
  }
}

然后就是自动跟随系统主题色,这个就需要用媒体查询了,也就是prefers-color-scheme,实现如下:

@media (prefers-color-scheme: light) {
  :has(#auto:checked){
    body{
      --bg: aliceblue;
      --color: #000;
    }
  }
}
@media (prefers-color-scheme: dark) {
  :has(#auto:checked){
    body{
      --bg: #000;
      --color: #fff;
    }
  }
}

这样就可以实现三种主题模式的动态切换了,效果如下:

你也可以访问以下在线链接查看实际效果

  • CSS prefers-color-scheme (codepen.io)[1]
  • CSS prefers-color-scheme (juejin.cn)[2]

二、light-dark 和 color-scheme

除了上面这种方式,现在light-dark也能实现类似的效果。

https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark

light-dark是一个CSS函数,语法很简单,只需要传两个值。

/* 颜色 */
color: light-dark(black, white);

/* 自定义属性 */
color: light-dark(var(--light), var(--dark));

第一个值是在白天模式下的值,第二个是在黑夜模式下的值。

那这个模式是由什么决定的呢?答案就是color-scheme。

回到前面的例子,如果用light-dark实现会更加简单。

:root{
  --bg: light-dark(aliceblue, #000);
  --color: light-dark(#000, #fff);
}
:has(#light:checked){
  body{
    color-scheme: light;/*白天模式*/
  }
}
:has(#dark:checked){
  body{
    color-scheme: dark; /*黑夜模式*/
  }
}
:has(#auto:checked){
  body{
    color-scheme: light dark; /*自动模式*/
  }
}

简单解释一下,首先提前定义好白天和黑夜模式下的值,然后在切换主题的时候就不是改值了,而是改color-scheme。

同样可以实现三种主题模式的动态切换了,效果如下:

你也可以访问以下在线链接查看实际效果

  • CSS light-dark (codepen.io)[3]
  • CSS light-dark (juejin.cn)[4]

是不是比前面的实现方式更简单了,而且思路更加直观了

三、更灵活的主题适配方式

在实际需求中,不仅仅有黑夜和白天,还有各种各样的主题色。这些主题色往往还会区分白天和黑夜,毕竟同一种红色在白色背景和黑色背景观感肯定是不同的。

比如下面这种颜色,在黑色背景上就会有些突兀,或者刺眼。

所以,主题色也应该区分白天和黑夜。

下面实现一个主题色和白天/黑夜模式自适应搭配的案例。

我们再使用input radio来创建几个主题色选项。

<fieldset>
  <label>主题色</label>
  <input type="radio" name="color" value="red" id="red" checked><label for="red">红色</label>
  <input type="radio" name="color" value="blue" id="blue"><label for="blue">蓝色</label>
  <input type="radio" name="color" value="green" id="green"><label for="green">绿色</label>
</fieldset>
<fieldset>
  <label>黑暗/白天模式</label>
  <input type="radio" name="theme" value="light" id="light" checked><label for="light">白天</label>
  <input type="radio" name="theme" value="dark"  id="dark"><label for="dark">黑夜</label>
  <input type="radio" name="theme" value="auto"  id="auto"><label for="auto">自动</label>
</fieldset>
<button>前端侦探</button>

然后,给每种颜色用 CSS变量定义好,并且每种主题色都包含白天、黑夜两种颜色,如下:

:root{
  --bg: light-dark(aliceblue, #000);
  --primary-red: light-dark(rgb(255, 69, 69), rgb(119, 2, 2));
  --primary-blue: light-dark(rgb(0, 68, 255), rgb(36, 36, 154));
  --primary-green: light-dark(rgb(0, 214, 61), rgb(5, 94, 5));
  --primary-color: var(--primary-red);
}

然后在切换主题色时,改变--primary-color就行了。

/*主题色修改*/
:has(#red:checked){
  body{
    --primary-color: var(--primary-red);
  }
}
:has(#blue:checked){
  body{
    --primary-color: var(--primary-blue);
  }
}
:has(#green:checked){
  body{
    --primary-color: var(--primary-green);
  }
}

这样主题色修改和白天/黑暗模式修改就彻底分离开来,在实现上也更加清晰明了。

下面是实际效果演示,可以明显看到不同模式下的主题色是不同的。

你也可以访问以下在线链接查看实际效果

  • CSS light-dark primary (codepen.io)[5]
  • CSS light-dark primary (juejin.cn)[6]

四、兼容性和总结

再来说一下兼容性,要求 Chrome 123+,虽然是刚推出来不久,但现在(2024-6-22)所有浏览器都已经兼容了。

这意味着已经是一个标准了,放心学习,下面总结一下本文要点

  • 网站一般会有三种主题模式,白天、黑夜、自动跟随系统
  • 自动跟随系统主题色,需要用媒体查询prefers-color-scheme
  • light-dark语法很简单,可以传两个颜色,分别是白天模式和黑夜模式的颜色
  • light-dark的颜色模式由color-scheme来决定
  • light-dark可以以更灵活的方式来适配各种主题色

light-dark可以说是 web 上关于主题颜色的终极解决方案了,期待可以早日使用。

[1]CSS prefers-color-scheme (codepen.io): https://codepen.io/xboxyan/pen/KKLoEjB。

[2]CSS prefers-color-scheme (juejin.cn): https://code.juejin.cn/pen/7383215058630737972。

[3]CSS light-dark (codepen.io): https://codepen.io/xboxyan/pen/mdYxgVm。

[4]CSS light-dark (juejin.cn): https://code.juejin.cn/pen/7383215549599186954。

[5]CSS light-dark primary (codepen.io): https://codepen.io/xboxyan/pen/LYodvLR。

[6]CSS light-dark primary (juejin.cn): https://code.juejin.cn/pen/7383215899521597474。

责任编辑:姜华 来源: 前端侦探
相关推荐

2023-11-06 09:24:14

CSS相对颜色

2021-06-30 13:37:17

UbuntuYaru 社区开发

2023-11-20 09:27:28

CSS前端

2010-09-08 14:53:51

CSS继承

2024-03-25 09:20:22

CSS语法fixed

2020-10-13 07:00:15

Vue Vite应用程序开发

2018-02-02 16:08:32

互联网大数据数据分析

2015-08-26 16:17:49

OpenStack OpenStack 架开源云平台

2023-06-26 09:16:34

CSScolor-mix

2010-09-14 11:19:23

DIV+CSS技术

2023-12-11 13:09:00

CSSlinear缓冲函数

2009-11-17 09:47:54

Oracle SQL语

2016-12-30 13:43:35

异步编程RxJava

2021-11-22 22:14:46

JavaScript开发模块

2009-11-13 15:55:52

Oracle哈希连接

2022-08-04 18:50:12

Navigator浏览器设备

2010-08-23 16:23:53

CSS+DIV

2010-09-13 13:21:29

CSS排版

2010-09-08 14:00:08

marginCSS

2021-04-13 09:07:33

InnoDB内存结构
点赞
收藏

51CTO技术栈公众号