CSS-in-JS vs 传统CSS:现代样式方案选择指南
CSS-in-JS vs 传统CSS:现代样式方案选择指南
大家好,我是小陈,一个普通得不能再普通的前端程序员。每天在代码的海洋里游荡,不是在调试样式,就是在去调试样式的路上。最近我经历了一件让我颇为感慨的事情——关于到底该用 CSS-in-JS 还是继续使用传统的 .css 文件这个“世纪难题”,彻底点燃了我和同事们之间的争论。
今天我想聊聊我的亲身体验,也许能帮你们少走些弯路,也可能让你在某个深夜改样式到抓狂的时候,觉得:哦,原来不止我一个人这么惨。
开篇:样式之争从何而来?
事情还得从我们公司最近启动的一个新项目说起。这是一个中等规模的 React 应用,目标用户群体比较年轻,UI 设计也比较炫酷,动效多,组件复用性强,主题切换功能也是刚需。团队一拍即合,准备搞点新鲜玩意儿——比如 CSS-in-JS 方案。
我当时一听就觉得:“哦豁,终于不用再写那种全局冲突的 class 名字了。”毕竟以前项目里常出现 .title, .content, .box 这种名字,然后被不同人重复定义,最后谁也不知道哪个才是正主。那感觉就像在菜市场吵架,全是人声,听不清一句重点。
所以一开始我对 CSS-in-JS 是持支持态度的,甚至有点小兴奋,想着这会不会是我们告别“CSS 维护地狱”的曙光。
经历:一场美丽的误会
我们选用了 styled-components 作为样式解决方案,理由很简单:
- 支持动态传值,可以配合 React 的 props;
- 主流且社区活跃;
- 和 TypeScript 配合也不错(至少当时官网这么说);
项目初期确实爽得不行。每个组件都有自己的“专属样式”,不需要跳来跳去地找 CSS 文件。比如写一个按钮:
const MyButton = styled.button`
background-color: ${props => props.primary ? '#3f51b5' : '#fff'};
color: ${props => props.primary ? '#fff' : '#000'};
padding: 10px 20px;
`;
看起来是不是很优雅?参数化、逻辑化、组件化三合一,简直美得不像话。那时候我觉得:传统 CSS 真的要被淘汰了。
可没过多久,事情就开始变得微妙了。
首先是构建速度明显变慢,热更新时间从原来的几秒变成了十几秒,尤其当我们在本地开发时经常卡顿,仿佛浏览器和 Webpack 在偷偷谈恋爱,不让我们打扰。
其次是样式隔离的问题并没有想象中那么美好。虽然每个组件有自己的类名,但有时候你还是要覆盖第三方库的样式,这时候你就得写 &&& 或者其他奇怪的选择器,搞得比传统 CSS 还混乱。
最离谱的是,某次上线后我们收到了一个 bug 报告:生产环境下的某些样式居然丢失了!排查半天才发现,是因为 Webpack 的 Tree Shaking 搞掉了某些未显式引用的组件样式。这就尴尬了,原本以为模块化的优点,结果成了隐患。
更别说在多人协作的项目中,每个人对 CSS-in-JS 的写法都略有不同,有的喜欢内联对象风格,有的偏爱模板字符串,最后整个项目的样式层像一锅乱炖。
感受:理想丰满,现实骨感
那段时间,我常常一边写着样式一边陷入沉思:
“我到底是在写样式,还是在写 JavaScript?”
“为啥一个简单的边框圆角也要写成函数?”
“为什么我在审查元素的时候看到的都是随机生成的类名?”
我记得有次加班到深夜,为了调试一个 hover 效果,查了半天发现是 props 传递错了,气得差点把显示器踹飞。那一刻我真的想说:CSS-in-JS 能解决的问题,传统 CSS 也能解决;而 CSS-in-JS 带来的麻烦,传统 CSS 却未必会有。
当然,也不能一棍子打死它。CSS-in-JS 在一些场景下确实表现出色,比如组件需要根据状态动态变化,或者你想做一些 fancy 的动画过渡。但它并不是万金油,尤其是在中大型项目里,如果没有良好的规范和结构设计,很容易变成“样式地狱 Plus”。
转折:重新审视传统CSS
就在我开始怀疑人生的时候,一位老同事悄悄告诉我:“要不要试试用 SASS 再加上 BEM 规范写?别急着否定传统方案。”
我心想:你这是想让我回到刀耕火种的时代吗?但出于好奇,我还是花了一个周末尝试了一下。
我试着重构一个小模块,用 SCSS 模块化引入,并严格按照 BEM 的命名规范来写:
.block {
&__element {
// ...
}
&--modifier {
// ...
}
}
结果我发现,其实一切也没那么糟。
- 构建速度快了;
- 样式层级清晰;
- 审查元素时能看到明确的类名;
- 修改起来也更容易定位问题;
而且,SCSS 提供的嵌套、变量、mixins 等特性,完全可以弥补传统 CSS 的不足。更重要的是,当你需要做性能优化、SEO 友好、或 SSR 渲染时,传统 CSS 的优势就显现出来了。
我又开始反思自己当初的偏见:是不是我们太急于追求“流行”和“创新”,反而忽略了实际工程实践中的稳定性和维护性?
思考:没有银弹,只有权衡
经历了这一轮折腾之后,我逐渐明白:
CSS-in-JS 并不是必须,也不是错误;同样,传统 CSS 也不是落后的代名词。关键在于你的项目需求、团队习惯、以及你是否真正了解这些技术的本质。
如果你是一个独立开发者或者中小型项目,想要快速实现组件化样式、方便的主题切换、动态样式调整,那 CSS-in-JS 真的很好用。
但如果你在一个大团队中参与长期维护的复杂系统,或者你对页面加载速度、SEO、SSR 有一定要求,那你真的得慎重考虑 CSS-in-JS 是否值得为你带来潜在的成本。
另外,还有一个现实问题是:工具链生态。CSS-in-JS 往往依赖特定的构建流程、插件支持、IDE 插件等等。一旦你的项目升级或者迁移,可能就会遇到不少兼容性问题。而传统 CSS 则更加“稳如老狗”。
展望与建议:未来的路该怎么走?
站在当下,我并不反对任何一种方案,反而是学会了“按需取材”。我们最终采用了混合方案:
- 对于核心 UI 组件,采用 CSS-in-JS 来增强可定制性和封装性;
- 对于通用布局、基础样式、公共样式,则用 SCSS + BEM 写在全局文件中;
- 同时加强团队内部的样式规范培训,避免重蹈覆辙。
我也给正在纠结这个问题的你几点建议:
- 不要盲目追新,也不要固守旧模式。每种方案都有其适用场景。
- 关注团队协作。再牛的技术如果团队不会用、不好维护,那就是灾难。
- 多动手试错,少看网上的测评文章。别人的经验只是参考,亲身实践最重要。
- 注重性能和可维护性。特别是中大型项目,不要为短期便捷牺牲长期成本。
- 保持开放心态。未来可能会有更多的样式方案出现,比如 Tailwind CSS、Vanilla Extract、Linaria 等,都要保持学习的态度。

结语:样式之战,其实是人心之战
回想这段历程,我觉得真正的战斗从来都不是技术层面的,而是我们对于“如何更好地组织和维护代码”的持续思考。
CSS-in-JS 也好,传统 CSS 也罢,它们本质上只是工具,真正决定成败的永远是我们如何运用这些工具。
愿你在每一次写样式的时候都能心平气和,不再为 class 名字绞尽脑汁,也不会因动态 props 失眠。毕竟,作为一名前端程序员,我们最大的敌人从来不是 JS、不是 CSS、也不是框架,而是“不确定明天产品经理又会提什么需求”。
感谢你读到这里,如果你也有过类似的经历,欢迎在评论区吐槽或分享你的做法。也许下一次争论的主角,就是你我他。
Peace! ✌️

评论 0