CSS-in-JS 还是传统 CSS?我踩过的坑比你写的样式还多

★许思涵
2026-02-11 03:07
阅读 660

上周五晚上十一点,我盯着屏幕里一个诡异的样式冲突,差点把咖啡泼到键盘上。又是那个经典问题:某个组件的 padding 被全局样式覆盖了,而这个 Bug 居然在本地跑得好好的,一上线就炸。这已经不是第一次了。作为一名远程办公两年、靠 GitHub Copilot 写代码续命的前端老油条,我终于决定认真梳理一下:到底该用 CSS-in-JS 还是传统 CSS?

说起来,我从 2022 年初就开始用 GitHub Copilot 付费版,快两年了。它帮我写了无数行 styled-componentsemotion 的代码,也让我在赶项目 deadline 时少掉几根头发。但最近公司准备重构一个老后台系统,技术选型会议上,新来的实习生居然问:“CSS-in-JS 不是过时了吗?” 我当场愣住——这届年轻人,是不是被某些博客带偏了?


一次线上事故引发的思考

事情得从去年双11说起。我们团队负责一个电商管理后台,用了好几年的 Sass + BEM 命名规范。按理说很稳,结果那天凌晨三点,运维突然拉群:“用户列表页样式全乱了!” 我睡眼惺忪地爬起来一看,好家伙,class="user-list__item--active" 被另一个模块的 .list-item.active 覆盖了。

原因?某个同事在写新功能时,为了“快速上线”,直接在全局加了个 .active { color: red !important; }。产品经理催得紧,测试又没覆盖 UI 回归,于是……线上事故。

那一刻我真的想砸电脑。传统 CSS 的作用域问题,又一次把我们坑惨了。

但转头看 CSS-in-JS 呢?也不是银弹。我之前在一个内部工具项目里用 styled-components,结果打包体积暴涨 40KB,Lighthouse 性能分直接掉到 65。更别提 SSR 时的 hydration mismatch 报错,debug 到怀疑人生。

所以,没有绝对正确的选择,只有更适合当前场景的方案


DeepSeek 时代,样式方案也在进化

最近我用 DeepSeek 看了一些大厂的开源项目,发现趋势挺有意思。比如 Vercel 的 Next.js 官方示例,现在默认推荐用 Tailwind CSS;而 Shopify 的 Hydrogen 框架则坚定拥抱 CSS Modules。Meta 的 React 团队虽然早期力推 stylex(他们内部的 CSS-in-JS 方案),但对外开源项目却多用纯 CSS。

这说明什么?工程化思维正在取代“技术站队”

我翻了翻 GitHub 上近半年的 star 增长趋势:

方案 代表库 GitHub Stars (2023) 特点
传统 CSS Sass, PostCSS 稳定增长 成熟、工具链完善
CSS Modules - 中速增长 局部作用域、无运行时
CSS-in-JS styled-components, emotion 增速放缓 动态样式强、bundle 体积大
Utility-First Tailwind CSS 爆发式增长 开发效率高、学习曲线陡

看到没?Tailwind 的崛起不是偶然。它用原子类解决了传统 CSS 的命名焦虑和作用域问题,又避免了 CSS-in-JS 的运行时开销。难怪越来越多求职者在简历里写“精通 Tailwind”。


性能优化视角:别让样式拖垮你的 LCP

作为一个对性能优化有点执念的人,我专门测过几种方案的首屏加载表现(测试环境:React 18 + Webpack 5 + Chrome DevTools):

  • 传统 CSS(Sass):首屏 CSS 体积 28KB,LCP 1.2s
  • CSS Modules:首屏 CSS 26KB,LCP 1.1s
  • styled-components(客户端渲染):首屏 JS 增加 35KB,LCP 1.8s
  • Tailwind(purged):首屏 CSS 19KB,LCP 0.9s

结论很明显:CSS-in-JS 在性能敏感场景(比如 landing page)是劣势项。它的动态注入机制依赖 JavaScript 执行,而浏览器渲染 CSS 是原生高效的。

但!如果你在做高度动态的仪表盘或数据可视化应用,比如根据用户权限实时切换主题色,那 CSS-in-JS 的 props => css 能力简直救命。我之前写一个爬虫监控面板,需要根据任务状态动态改变进度条颜色,用 emotion 三行代码搞定,换成传统 CSS 得写一堆 class 切换逻辑。


我的实战选择策略

经过这几年的折腾,我总结了一套“人话版”选型指南:

选传统 CSS(或预处理器)如果:

  • 项目是内容型网站(博客、文档站、营销页)
  • 团队有设计师提供 Figma 标注,且设计系统稳定
  • 对 bundle 体积极度敏感(比如 PWA 或低端机用户多)
  • 你讨厌调试 data-css-hash 这种神秘属性

选 CSS-in-JS 如果:

  • 应用 UI 高度动态(比如主题切换、实时数据驱动样式)
  • 组件库开发,需要强封装性(避免样式泄露)
  • 团队全是 React 老手,能接受额外的学习成本
  • 你愿意为开发体验牺牲一点性能(且用户设备较新)

选 Tailwind / Utility-First 如果:

  • 你追求极致的开发速度
  • 设计系统原子化(间距、颜色、字体都有 token)
  • 不想纠结命名(告别 btn-primary-large-hover 这种噩梦)
  • 项目周期短,需要快速交付 MVP

Copilot 教我的事:工具只是杠杆

说到这儿,不得不提 GitHub Copilot。它确实能帮我快速生成 styled.buttontw 类,但它不会替我做架构决策。有一次我让它写一个 Modal 组件,它默认用了 styled-components,结果我手动改成 CSS Modules + :global() 来兼容第三方图标库。

工具再强,也得人来掌舵。就像我去年面试一个候选人,他滔滔不绝讲 CSS-in-JS 的好处,但当我问“如何处理服务端渲染时的样式一致性”时,他卡住了。技术深度,永远藏在细节里


最后一点真心话

别被社区的 hype 带着跑。CSS-in-JS 没死,传统 CSS 也没过时。关键是你能不能根据项目上下文做权衡

我现在的新项目,混合使用了三种方案:

  • 全局布局用 Sass(变量 + mixin 复用)
  • 业务组件用 CSS Modules(隔离作用域)
  • 动态部分用 clsx + Tailwind 工具类(快速响应状态)

效果?Bundle 体积控制住了,开发效率也没降,线上再也没出现过“神秘样式覆盖”事故。

所以下次再有人问“哪个更好”,你可以笑着回他:“看需求,兄弟。”

毕竟,我们不是在写代码,是在解决问题。而解决问题的人,从来不会被工具绑架。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝