再谈原子类
过去两年中,我从初步尝试CSS原子类,再到成为原子类的重度依赖用户,深刻体会到了原子类的优点和缺点,再开篇文章记录一下。
之前写的关于原子类的一些文章
优势
代码可迁移性好
在传统的css开发中,有的同学习惯将相关模块的代码一层一层进行嵌套,看起来比较模块化,但实际上这种写法有很多弊端
- 样式迁移很难,比如页面结构调整,需要将某段HTML模版挪到其他地方,除了修改HTML代码之外,还需要小心翼翼地从SCSS等样式表源码中,将这部分样式抽出来
- 样式权重比较高,如果需要覆盖样式,需要添加更重的权重,或者使用
!important
,显然两种方式都不好 - CSS解析是从右向左的,演示选择器过长,存在解析性能问题
原子类最核心的一点是将样式和HTML结构绑定在了一起,这里的HTML包含了传统HTML
、Vue Template
和React JSX
等
- 只要有HTML代码,就有了样式,可以快速迁移一段具有样式的HTML结构,提升开发效率
- 在删除HTML的时候就删除了对应的样式,不会导致HTML结构删除了,但CSS代码还留在那里,容易维护
- 开发时不用HTML和CSS来回切换,也基本不再需要通过开发者工具看某个样式来自哪个样式类,提升开发效率
当需要对布局代码进行重构或者迁移的时候,这个特性非常有用。
在管理后台等大量使用组件库的项目中,使用原子类,基本上不再需要写单独的样式表了。
构建性能
与LESS、SCSS等CSS预处理器相比,unocss等原子类框架的构建性能往往更好,原因有
- 没有复杂的变量定义、类嵌套、mixin、extend、for、if等语法,编译更轻量
- 按需生成代码中出现的原子类代码,不需要处理项目中大量的
*css
文件文件,构建内容少,且相同的原子类只会构建一次
更快的构建性能,可以提供更快的热更新速度,以及更快的构建速度,也会带来更好的开发体验。
避免样式冲突
原子类从源头解决了样式冲突的问题,也不需要再考虑样式类命名(进一步提升开发效率),不需要使用BEM等很长的命名规范。
不存在样式冲突,也就不需要使用scoped css
、css modules
等技术了,这里点名批评css modules
,写起来太难受了,违背了JSX all in one
的流畅开发体验。
精简样式表体积
在使用传统的css命名规则(如BEM等)的项目中,最终会得到一个几百k的样式表,原子类可以在单条属性规则的粒度上复用样式,极大程度减少了样式表的大小。
同时,在删除HTML之后,对应的原子类会被移除掉,原子类框架现在支持按需编译,也就不存在HTML删了、CSS代码还在的问题,解决了样式表冗余的问题。
劣势
学习成本
初学者的学习成本还是比较高,即便是写了很长一段时间的老手,在面对某个不常用的样式时,可能还是得去翻一下文档看看对应的原子类怎么写。
class很长
class内的字符变得很长
- 这个某些人觉得阅读性很差,但我觉得可以直接从代码就看见这个元素的样式,还是很方便的
- 如果是使用vue或者react,会造成编译的render函数变大,也就是最后的js文件会变大一点
无法从设计图复制css
无法直接从figma、蓝湖等地方拷贝样式代码,我个人是比较能接受的,毕竟直接复制的代码很冗余。
目前部分设计工具也支持导出tailwind了,比较其命名是比较规范的,转成原子类的成本并不高。
使用心得
多使用继承
多使用样式继承等CSS特性,可以进一步减少需要编写的原子类,比如字体、行高、颜色等可以从父元素继承的样式,就不用再每个子元素都写一遍样式类了。
配置项而非字面量
如果有机会,最好是将常用的颜色、字号、尺寸等在配置文件中进行声明(需要设计师配合),然后通过配置名而非字面值的形式来编写样式类,比如使用leading-normal
而不是leading-[24px]
来写行高
技术选型
目前主流的原子类框架似乎已经尘埃落地,tailwindcss一马当先,windicss已经不再更新新功能了(虽然我过去基本都在使用这个),幸好unocss提供了各种预设,让我们可以在自己喜欢的原子类框架之间进行选择。
不同的原子类框架,其语法特性有一些相似的地方,也有不同的地方,就像不同的编程语言一样。
比如WindiCSS 其实是一个旨在加速 TailwindCSS 的替代实现,因此它基本上完全兼容 TailwindCSS 的语法,但也扩展了一些自己的语法。
这导致在项目初始化时,原子类的框架选型会比较重要,目前建议使用unocss
,然后选择自己熟悉的preset。
TODO
在我后续负责的前端项目中,CSS的技术选型方面,我会优先选择原子类框架。
后续有新的感受再继续补充。
你要请我喝一杯奶茶?
版权声明:自由转载-非商用-保持署名和原文链接。
本站文章均为本人原创,参考文章我都会在文中进行声明,也请您转载时附上署名。