现代前端工程 CSS 方案调研
date
Apr 4, 2022
slug
css_solutions
status
Published
tags
web
type
Post
URL
summary
Author
随着这几年前端技术的快速发展,前端工程化里的 CSS 方案也在一直更新,本文简单总结分享一下目前比较常见的一些 CSS 方案。
首先可以大概分为四个大类:
- CSS 预处理器
- CSS Modules
- CSS-in-JS
- CSS 原子化
CSS 预处理器
CSS 预处理器是出现比较早的一种 CSS 方案,比较流行的预处理器方案有 Less、SASS、Stylus、PostCSS。
这几个方案各有优缺点,其中 Less 最简单,语法也比较简单,出现的也比较早可以搭配各种构建工具使用,缺点就是编程能力太弱,这部分 SASS 比较强大一点,但是SASS 一是语法太强大二是NPM安装比较麻烦,所以很多人也不是很喜欢用,觉得简单的Less 就足够用了。
Stylus 是一个富于表现力、动态的、健壮的 CSS 方案,因为写法和普通的CSS 方案差别比较大,所以这个受众也比较小。PostCSS 虽说也是预处理器,但是和其他三个有点不一样,它是一个使用JavaScript 工具和插件转换 CSS 代码的一个工具,它的强大之处在于可以结合很多插件来处理CSS,它可以达到预处理器的作用,但是它的功能不仅于此。
CSS Modules
JS在 ES6 之前诟病最多的就是缺少原生的模块功能,CSS 也是如此,没有模块功能导致写的一些CSS经常被全局污染需要写很多嵌套,为此社区出现了 CSS Modules这一技术方案,它就是为了给 CSS加了局部作用域和模块依赖功能。CSS Modules 是在编译的时候会给你的类生成一个全局唯一类名, 一出来就受到很大的关注,因为大家真的不喜欢给 CSS 类取名,有了它就不用担心会有 CSS 冲突了,也不需要写各种嵌套了。
CSS-in-JS
随着React 的流行,在JS里面写CSS也开始变得慢慢流行起来,随着不断发展和迭代目前社区存在的几种CSS-in-JS 方案如下:
- styled-components
- emotion
- vanilla-extract
- stitches
- compiled
其中styled-components是最早流行的该方案,著名React 框架 Next.js 还内置了该CSS 方案,它把HTML原生标签封装到styled对象里面,把CSS 以字符串的形式传入,还支持传入props 动态生成CSS,最后会生成一个class。而且styled-components 因为出现的比较早,生态成熟,提供了各种编辑器插件提升开发体验。
但是因为所有带样式的基础HTML标签在styled-components以React组件存在,大量使用对性能带来一定影响。
emotion 是一个高性能、灵活的CSS-in-JS库。介绍两种使用方式,一种是和框架无关,一种是在React 里使用。在React中使用第一行注释是说明让babel用 jsx 函数对jsx文件进行处理,而不是 React.createElement。最后都会生成一个 class。
emotion 支持 Object Styles 和 String Styles 两种写法。
emotion 通过 @emotion/styled 还支持styled-components的语法,而且比styled-components有更小的文件和更快的渲染速度。它还支持SourceMap,调试也更方便。
vaillan-extract 是一个 Zero-runtime Stylesheets-in-TypeScript的 CSS 框架,将样式写入TypeScript(或JavaScript)中,使用局部作用域的类名称和CSS变量,然后在构建时生成静态 CSS 文件。
它的实现和前端框架无关,可以搭配不同的构建工具使用,支持局部作用域的类名和 css 变量,zero-runtime 保证了在构建时生成了所有的样式,性能方面比styled-components这些方案要好。
stitches 是一个接近零运行时,支持SSR的轻量高性能的 CSS-in-JS解决方案。官方提供和框架无关的使用方式以及React的使用方式。
stitches 性能好,但是没有那么夸张,仅比emotion打包出来的体积小一点点,搭配TS开发体验很好,但是不支持字符串形式的 CSS 声明。
compiled 一个熟悉且高性能的适用于React的css-in-js库,TS支持很好,开发体验不错,提供多种使用方式。缺点就是比较新,社区生态啥的比较差,不建议直接上生产使用。
如图:提供 styled,CSS Prop,ClassNames 三种写法。
综合来说 css-in-js 里面比较突出的方案还是 emotion。
原子化CSS
原子化css其实不是一个新鲜的方案,记得早期没有前端构建工具的时候就有人讨论过这种写法,但是在当时大家并不认同这种写法,但是最近随着TailwindCSS在国外的流行,大家又开始关注了,TailwindCSS能流行起来一是它确实做的比较强大和完善,二来也是现在的构建工具比较强大,支持很多自定义功能。
Tailwind CSS 是一个功能类优先的 CSS 框架,它集成了诸如 flex, pt-4, text-center 和 rotate-90 这样的的类,它们能直接在脚本标记语言中组合起来,构建出任何设计。
不过虽然 Tailwind CSS 比较流行了,但是它的争议还是很多,和很早之前质疑这些原子化CSS的说法都差不多,比如说类名太多,难以维护扩展等。国内的相关争议可以在知乎上看看大家的讨论 https://www.zhihu.com/question/337939566
Windi CSS 是下一代工具优先的 CSS 框架。可以把 Windi CSS 看作是按需供应的 Tailwind 替代方案,它为你提供了更快的加载体验,完美兼容 Tailwind v2.0,并且拥有很多额外的酷炫功能。可以认为是开发体验更好的 Tailwind。
UnoCSS 是另外一个比较新的即时原子化CSS引擎,它的一个优点就是可以完全自定义规则,如果能接受原子化CSS的但是不想被tailwind css预先设计的样式约束 可以尝试一下。
总结
最后再总结一下我个人会在什么场景使用什么方案:
大型项目,多人协作的项目:CSS Modules 是个不错的方案,不用担心 CSS 冲突。
个人开发维护的小项目:Tailwind/Windi CSS 是不错的方案,可以使用 Less 做备选。
组件库:可以考虑使用 emotion 这些 css-in-js 方案,一个组件在一个文件里就能写完,不需要创建那么多的css 文件。