CSS-in-JS vs 传统CSS:现代样式方案选择指南

风度翩翩
2025-06-13 02:49
阅读 629

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 写在全局文件中;
  • 同时加强团队内部的样式规范培训,避免重蹈覆辙。

我也给正在纠结这个问题的你几点建议:

  1. 不要盲目追新,也不要固守旧模式。每种方案都有其适用场景。
  2. 关注团队协作。再牛的技术如果团队不会用、不好维护,那就是灾难。
  3. 多动手试错,少看网上的测评文章。别人的经验只是参考,亲身实践最重要。
  4. 注重性能和可维护性。特别是中大型项目,不要为短期便捷牺牲长期成本。
  5. 保持开放心态。未来可能会有更多的样式方案出现,比如 Tailwind CSS、Vanilla Extract、Linaria 等,都要保持学习的态度。

前端性能优化图表-1


结语:样式之战,其实是人心之战

回想这段历程,我觉得真正的战斗从来都不是技术层面的,而是我们对于“如何更好地组织和维护代码”的持续思考。

CSS-in-JS 也好,传统 CSS 也罢,它们本质上只是工具,真正决定成败的永远是我们如何运用这些工具。

愿你在每一次写样式的时候都能心平气和,不再为 class 名字绞尽脑汁,也不会因动态 props 失眠。毕竟,作为一名前端程序员,我们最大的敌人从来不是 JS、不是 CSS、也不是框架,而是“不确定明天产品经理又会提什么需求”。


感谢你读到这里,如果你也有过类似的经历,欢迎在评论区吐槽或分享你的做法。也许下一次争论的主角,就是你我他。

Peace! ✌️

评论 0

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