常见方案
CSS | CSS-in-JS | TailwindCSS | |
---|---|---|---|
学习曲线 | |||
动态样式支持 | |||
可维护性 | (配合BEM等) | (模块化、隔离) | (HTML中类名较多) |
性能 | |||
适合场景 | 静态页面、小型项目 | React等现代框架 | 快速开发、设计系统 |
全面对比
解决方案 | 代表/示例 | 核心概念/描述 | 优点 | 缺点 | 示例/实践 |
---|---|---|---|---|---|
CSS 预处理器 | Sass、Less、Stylus | • 变量、嵌套规则、混合器(Mixin)、继承(Extend)、运算 • 提供变量、嵌套、循环等高级功能 • 提供强大工具和逻辑控制(条件、循环) | • 提升CSS开发效率,代码模块化,易维护 • 提供逻辑控制功能 • 提升可读性与复用性 | • 需要编译,增加开发流程复杂性 • 生成CSS可能冗余,性能优势较低 | 使用Sass编写变量和嵌套规则 |
CSS in JS | Styled-components、Emotion、JSS | • 样式与组件绑定,动态生成CSS • 支持模块化与作用域隔离 • 在JS中编写CSS,常用于React等框架 | • 与React等框架无缝集成,动态样式管理简单 • 避免全局样式污染 • 动态能力强,与框架集成度高 | • 运行时性能开销大 • 学习曲线较陡峭 • 依赖构建工具 | 使用Styled-Components或Emotion编写样式 |
CSS模块化 | Webpack支持 | • 将CSS分隔为独立模块,通过工具生成独特类名 • 自动生成唯一类名避免冲突,样式按需加载 • 确保样式隔离 | • 避免命名冲突,性能优于CSS in JS • 适合模块化项目,维护性强 • 作用域隔离 | • 需要构建工具支持 • 动态样式支持不够灵活 • 上手复杂 | 使用CSS Modules引入局部样式 |
原子化CSS / Utility-First CSS | Tailwind CSS、Bootstrap Utilities | • 提供大量小型功能类名,通过组合构建页面 • 每个类名对应一个样式属性,样式通过类名组合实现 | • 快速开发,无需自定义CSS规则 • 样式统一,社区生态强大 • 减少样式冲突 | • 学习成本高(大量类名) • HTML文件样式类名多,可读性较差 • 类名杂乱 | 使用TailwindCSS的类名组合 |
Scoped CSS | Vue scoped样式、Shadow DOM | • 样式作用域限制在组件内 • 通过Vue的scoped或Web Components的Shadow DOM实现 | • 样式隔离强,代码结构清晰 • 不受外部影响 • 与组件绑定 | • 需要工具链支持 • 增加复杂性,全局样式覆盖困难 • 复杂项目中可能有性能问题 | Vue中通过<style scoped> 实现样式隔离 |
Functional CSS | Tachyons | • 样式为功能块,极简类名代表单一功能 • 类似原子化CSS,但更注重功能抽象化 • 通过工具函数生成,强调复用性 | • 功能清晰,简化CSS开发 • 易于理解和维护 • 减少重复代码,提高样式复用率 | • 可读性差,依赖文档记忆 • 学习成本较高 | 使用Sass函数生成间距:@function spacing($value) |
BEM命名规范 | - | • 基于类名的命名约定:Block(模块)、Element(元素)、Modifier(修饰符) | • 命名清晰,团队协作友好 • 无工具依赖,简单直接 • 清晰的语义和结构,高可维护性 | • 类名较长,增加代码冗长感 • 无法动态生成样式,灵活性低于CSS in JS • 手动管理易出错 | class="button__icon--large" |
PostCSS | - | • CSS工具平台,通过插件提供功能扩展(如自动前缀、变量) • 支持工具链的灵活配置 | • 灵活性强,插件链可定制 • 与现代构建工具无缝集成 • 插件灵活,结合现代CSS标准 | • 学习插件配置复杂,增加开发成本 • 需要熟悉插件生态 | 配置Autoprefixer和cssnano优化样式 |
如何对样式体系进行选型
- 项目特点
- 交付周期
- 性能需求
- 团队规模
- 未来扩展需求
- 模块化
- 响应式
- 动态样式
- 团队能力
- 技术栈工具链是否适配
- 熟练度
CSS方案技术评审
- 布局方案
- Flexbox 一维布局,弹性盒模型
- Grid 二维布局,复杂页面设计
- 动画过渡
- transition
- @keyframes
- CSS变量、计算属性
- 媒体查询
- @media
- 命名规范
- BEM 团队协作
- 工具化/语义话/原子类
- 性能
- 避免重排,重绘
- 避免position:absolute,float的复杂计算
- transform实现动画和过渡
- 优化
- contain
- 显式声明某个具有明确宽高的元素的渲染范围限制,(主要是跟子元素变动有关),以减少浏览器的重排和重绘工作。
- will-change
- 对会频繁样式变动的元素提前GPU加速优化
- 常见于 CSS 动画、滚动视差效果等场景
- will-change 会增加内存占用,过度使用可能降低性能。
- 尽量仅在需要时使用,效果完成后移除 will-change。
- contain
- 避免重排,重绘
CSS-in-Js方案
- 背景
- 由于组件化得到普及,这种方案能提供更好的动态样式和模块化
- 主流
- styled-components:易用,性能好
- Emotion:可ts,灵活性
- JSS:可复杂定制
- 特性
- 动态样式
- Scoped
- 嵌套、继承
- 最佳实践
- 性能:避免频繁修改
- 安全:ts辅助书写样式属性
- 主题系统切换
- 限制
- 大规模项目中的开销
- 兼容性
原子化(以Tailwind为例)方案
- 预定义类名,减少自定义样式从而提升生产效率
- 配置文件定义主题色,断点
- 高级用法
- @apply提取复用样式逻辑
- 动态值、状态修饰符
- JIT优化(v3.0+后默认启用了)
- 减少样式体积,提升构建速度,编译只生成最小需要的类
- 实践
- 类名排序、工具链规范以提升可读性
最佳实践
样式体系
- 分层架构
- Base Style全局样式基础
- Components组件样式
- Utilities工具类样式
- 原子化样式结合组件化
- 在小工具类 和 复用组件取得平衡
- 例如daisyui,先使用复用组件类,然后使用小工具类微调
- 在小工具类 和 复用组件取得平衡
- 工具链
- Linter进行样式检查
- stylelint,Prettier
- 比如缩进,引号,命名规范(正则检查),空块的约束
- CSS代码压缩,Tree Shaking
- 或者将以上放在CI/CD中自动化进行
- Linter进行样式检查
方案设计
- SSR项目: CSS/Moduler 定义全局规则
- ReactSPA:Css-in-Js 管理复杂交互
- 小项目,POC(Proof of Concept)快速:Tailwindcss
- 工具链
- Postcss处理自动前缀,变量
- Stylelint 保证代码规范
说实话Tailwind我觉得像daisyui那样去处理旧能很大程度避免HTML可读性极差的问题,虽然还是不如其他方案的HTML可读性,我觉得在团队规范合适的情况下,也适合大项目。