各大应用网站开始支持深色模式。那么对于前端来说,如何高效的支持深色模式呢?这里的高效指的是工程化、自动化。
PostCss原理和相关插件能力
简单来说,PostCss是一款编译Css的工具。PostCss具有良好的插件性,非常利于开发者进行扩展。PostCss工作原理:PostCss接收一个CSS文件,并提供插件机制,提供给开发者分析、修改Css规则的能力,具体实现方式也是基于AST技术实现的。
架构思路
对于主题切换,社区介绍的往往是通过CSS变量来实现的。那么如果是作为架构的话,其实这只是其中的一个环节,我们还应该思考以下几个问题:
- 如何维护不同主题色值?
- 谁来维护不同主题色值?
- 在研发和设计之间,如何保持不同主题色值的同步沟通?
- 如何最小化前端工程师的开发量,让他们不必硬编码两份色值?
- 如何使一键切换时的性能最优?
- 如何配合JavaScript状态管理,同步主题切换的信号?
我们以一个超链接样式为例,希望在开发时编写以下代码:
1 | a { |
这样就能一劳永逸直接支持两种主题模式,也就是说在应用编译时,上述代码将会被编译为下面这样:
1 | a { |
上述代码在构建阶段完成了以下操作:
- cc(GBK05A)这样的声明被编译为#646464。CC是一个函数,而GBK054是一组色值包含了浅色和深色两种主题模式中的眼颜色。
- 在HTML根节点上,添加属性选择器data-theme=’dark’,并添加a标签,color色值样式为#808080。
当构建完成后,用户点击切换主题按钮的时候,首先通过js脚本向HTML根节点标签内添加data-theme=’dark’的属性值。这时CSS选择器html[data-theme=’dark’]a将发挥作用,实现样式切换。
上面的逻辑很简单,那么我们回到架构设计中来,如何在构建阶段实现CSS样式编译转换呢?那就要依托于PostCss啦~
- 编写一个名字为postcss-theme-colors的PostCss插件,实现上述编译过程。
- 维护一个色值,这里用YML格式为例子,配置如下:
1
2
3
4GBK05A: [BK05, BK06]
BK05: '#808080'
BK06: '#999999'
postcss-theme-colors需要完成以下操作:
- 识别cc函数。
- 读取色组配置。
- 通过色值对cc函数求值,得到两种颜色,分别对应浅色和深色两种主题模式。
- 原地编译CSS中的颜色为浅色主题模式色值。
- 将深色主题模式色值写到HTML根节点上。
为了将深色主题模式色值写到HTML根节点上,我们又用到了两个PostCss插件,它们分别是postcss-nested
和postcss-nesting
。