用 HSL 实现响应式的颜色管理

202 阅读4分钟

为了方便阅读,我在最前面说下这么做的意义。

现时代的 CSS 框架,我们都是用 CSS 参数来定义 theme,为了定义以某个颜色为主基调的一个 theme,我们需要手搓相关的三十多个颜色,经典的一个 theme 例子如下:

:root {
    --primary:#bb1614;
    --on-primary:#ffffff;
    --primary-container:#ffdad5;
    --on-primary-container:#410001;
    --secondary:#775652;
    --on-secondary:#ffffff;
    --secondary-container:#ffdad5;
    --on-secondary-container:#2c1512;
    --tertiary:#705c2e;
    --on-tertiary:#ffffff;
    --tertiary-container:#fcdfa6;
    --on-tertiary-container:#261a00;
    --error:#ba1a1a;
    --on-error:#ffffff;
    --error-container:#ffdad6;
    --on-error-container:#410002;
    --background:#fffbff;
    --on-background:#201a19;
    --surface:#fff8f7;
    --on-surface:#201a19;
    --surface-variant:#f5ddda;
    --on-surface-variant:#534341;
    --outline:#857370;
    --outline-variant:#d8c2be;
    --shadow:#000000;
    --scrim:#000000;
    --inverse-surface:#362f2e;
    --inverse-on-surface:#fbeeec;
    --inverse-primary:#ffb4a9;
    --surface-dim:#e4d7d5;
    --surface-bright:#fff8f7;
    --surface-container-lowest:#ffffff;
    --surface-container-low:#fef1ef;
    --surface-container:#f8ebe9;
    --surface-container-high:#f3e5e3;
    --surface-container-highest:#ede0de;
}

是不是头都大了,对于不是很了解 CSS 和 color 原理的同学来讲,他怎么自助的定义 theme?

他可太难了!!!

因此我有一个想法,外行用户只需要说,他需要一个什么样的主色告诉系统。其他的颜色,比如冷色,暖色,亮色,暗色,相反色,渐变色,等等等等,全部通过计算得到。

而且完全不要 SASS 以及 LESS 这样的框架,CSS 即可做到了。

把定制 THEME 这件事情变成,用户在插件界面是自由选择一个基色,整个系统都不再有定义 theme 这件事情了,全部自动化掉。

可以理解为,插件系统提供了无限的 theme 供用户选择。

没错,就是自由选择,完全无限制,即随时响应用户的一个输入,生成整个 theme。

最后的结果是,上面那段复杂 theme,变成了一行 CSS 代码,这其中简化的工作量,恐怕不止一个星期吧:

:root {
   --primary:#bb1614;
}

======正文======================================

内容网站的Content页面往往会用两种颜色来做对比突出显示内容的背景,比如起点这样的: 下面是截图的免费章节。 image.png 文章的背景是一种颜色,而页面的背景则是同一个色系的更加 darken 的颜色。

为啥这样搞,人类这种生物啊,看什么东西都需要对比,包括看别人,没有对比就看不出区别,也不会有伤害。

一个页面,必须至少有两种颜色。

这样的颜色,总是要成组的出现,如果手写的话,那可就太麻烦了。

当然 SASS 的Lighten 函数是可以做到的。但我做的是嵌入进他人网站的插件,本来已经要花很多功夫来避免被原网站干扰了,是不太方便使用静态编译的 SASS ,以及引入大型 CSS 库的,而且出于性能考虑,也不能引入动态编译。

追求的就是简单,高效,无侵入。

而且我不只要亮度,还要控制色温,控制饱和度啊,要做到极致嘛。

能不能单纯用 CSS 实现呢?

当然是可以的啦,就是结合参数 var,计算函数 calc,以及 HSL 这个用饱和度,亮度和色相这三个很直白的进行定义的颜色的大杀器。

Hue 色相,Saturation 饱和度, Lighting 亮度。

HSL 就是用这三个数据来组成颜色,比如 hsl(205, 76%, 95%), 这个是内容网站使用最多的背景色。

很直白,比如对最后面的了亮度进行变化就可以控制颜色的亮度。。。

那么,我们只要找到自己喜欢的背景色,先把他转成 HSL 形式,剩下的就简单重复了,可以用 calc 和 var 做成自定义的函数啦控制 H S L 这三个数值。

So easy,下面是实战的例子。

这样就用 water 这个一个实例化的参数,得到了可用在多个组件中相应的颜色,效果和起点类似,但解决方案就简单太多了。

这么做有啥好处,首先,简单,其次,得到的 css 文件极小,第三,你不用在定义一堆 primaray,secondary ..blabla 了,统统让他们根据主色调自动响应,自己计算出来。

现在我可以很轻松就搞出很多主题了。