随着各个应用平台和网站都开始支持深色模式,相较于传统的页面配色方案,深色模式具有较好的降噪性,也能让用户的眼睛看内容更加舒适。
那么对于前端开发来说,如何高效的支持深色模式呢?这里的高效指的是工程化、自动化方案,不需要在开发过程中hard coding。
PostCSS原理及相关插件能力
postcss是一款使用JavaScript编写的用于编译css的工具,具有良好的插件性,非常有利于开发者扩展。
原理: PostCSS接受一个css文件,并提供了插件机制,提供给开发者分析、修改css规则,具体实现方式是基于AST技术。
设计主题切换功能前端自动化方案,站在架构的角度来说,需要思考的点有:
- 如何维护不同主题色值
- 谁来维护不同主题色值
- 研发和设计之间,如何保持不同主题色值的同步沟通;
- 如何最小化前端工程师的开发量,不需要hard coding两份颜色数值;
- 如何做到一键切换时的性能最优;
- 如何配合JavaScript状态管理,同步主题切换的信号
基于以上考虑,以一个超链接为例,我们希望做到在开发时,编写这样的代码:
a {
color: cc(GBK05A)
}
这样的代码,能直接支持两套(light/dark)主题模式,即在应用编译时,上述代码预期被编译为下面的代码
a{
color: #646464;
}
html[data-theme='dark'] a {
color: #808080;
}
我们看一下在编译时,构建环节发生了什么:
cc(GBK05A)
这样的声明,被编译为#646464
- 即
cc
是一个css function,而GBK05A
是一组色值,分别包含了light和dark两种主题的颜色 - 同时在HTML根节点,添加属性选择器
data-theme='dark'
,并添加a标签color色值样式为#808080
我们设想,用户点击“切换主题”按钮时,首先通过**JavaScript将HTML根节点标签添加data-theme
为dark
的属性值,这时CSS选择器html[data-theme='dark']
a将起作用,实现了样式的切换。
那么如何在构建时完成CSS的样式编译转换呢?答案指向PostCSS
- 首先编写一个名为postcss-theme-colors的postcss创建,实现上述编译过程
- 维护一个色值,结合上例即:
GBK05A: [ BK05, BK06 ]
BK05: '#808080'
BK06: '#999999'
postcss-theme-color需要:
- 识别
cc()
方法; - 读取色值
- 通过色值,对
cc()
方法求值,得到两种颜色,分别对应dark和light模式; - 原地编译css中颜色为light模式的色值
- 同时 dark 模式色值写到html节点上
为了将dark模式色值按照html[data-theme='dark']
方式写到HTML节点上,我们使用了另外两个Postcss插件完成 - PostCSS Nested
- PostCSS Nesting
一个PostCSS就是一个Node.js模块,开发者调用postcss.plugin
(源码链接postcss.plugin)工厂方法返回一个插件实体。
postcss插件编写模板:
var postcss = require('postcss')
module.exports = postcss.plugin('pluginname',function(opts){
opts = opts || {}
return function(css, result) {
// Transform the css ast
}
})
插件实体形如:
return {
postcssPlugin: 'PLUGIN_NAME',
/*
Root (root, postcss) {
// Transform CSS AST here
}
*/
/*
Declaration (decl, postcss) {
// The faster way to find Declaration node
}
*/
/*
Declaration: {
color: (decl, postcss) {
// The fastest way find Declaration node if you know property name
}
}
*/
}
}
在编写postcss插件时,我们可以直接使用postcss.plugin方法完成实际开发。