CSS-in-JS vs 传统CSS:现代样式方案选择指南 —— 一个裸辞Gap半年程序员的血泪复盘
去年十月,我坐在杭州出租屋的飘窗上,窗外是连绵阴雨,手里攥着刚被拒的第三家面试反馈邮件:“工程能力不错,但对现代前端技术栈理解不够深入”。那一刻,月薪从22k跌到0,房租3500块像刀子一样扎在心上。更难受的是,老婆在苏州,我们只能周末见面——而这个周末,我又得编个理由说“项目太忙”不去。
说实话,那会儿我对CSS-in-JS和传统CSS之争根本没概念。在前东家(某一线大厂),一切都有规范:SCSS + BEM + Webpack,稳如老狗。直到面试官冷不丁问:“你们项目为什么不用Emotion?Styling组件化怎么做的?”我支支吾吾,心里却在咆哮:老子连饭都快吃不上了,还管你用CSS还是JS写样式?
Gap期的觉醒:不是技术不行,是思维卡住了
Gap的第四个月,我开始啃GitHub Trending上的开源项目。偶然点进Vercel的Next.js模板库,发现他们大量使用styled-components;再翻翻Shopify的Polaris Design System,好家伙,Vanilla Extract玩得飞起。而反观自己维护过的内部管理系统,还是.btn-primary { background: #007bff; }这种祖传写法。
我突然意识到一个问题:产品形态变了,但我的样式思维还停在jQuery时代。
以前做大屏数据后台,用户量小、迭代慢、UI固定,传统CSS完全够用。可现在做的是To C产品——要快速试错、要主题切换、要服务端渲染(SSR)兼容、要TypeScript类型安全。这时候,传统CSS的全局污染、命名冲突、缺乏逻辑能力,就成了致命伤。
上周五晚上,我和老婆视频。她看我愁眉苦脸,问:“还在纠结那个样式方案的事?”
我说:“是啊,感觉选错了技术栈,整个项目都会翻车。”
她笑了:“你不是总说,技术没有银弹吗?别钻牛角尖。”
这句话点醒了我。CSS-in-JS不是银弹,传统CSS也不是垃圾——关键看你的“综合”场景。
真实项目中的血泪对比:我在两个极端都踩过坑
场景一:高迭代To C产品 → CSS-in-JS 是刚需
去年十二月,我接了个外包项目:一个社交类小程序,需求每周变三次,UI设计师恨不得每天改配色。客户要求“支持深色模式+节日主题动态切换”。
我一开始图省事,用SCSS写了一堆.theme-light .btn { ... }嵌套规则。结果第三周就崩了:
- 主题切换时闪白屏(因为CSS文件要重新加载)
- 某个按钮在深色模式下文字看不见(全局样式被覆盖)
- 新来的实习生不小心把
.card改成.cards,整个首页布局炸裂
痛定思痛,我重构为Emotion + CSS Variables方案:
// 主题上下文
const ThemeContext = createContext({ mode: 'light' });
// 按钮组件
const StyledButton = styled.button<{ $variant: 'primary' | 'secondary' }>`
background: ${props =>
props.$variant === 'primary'
? 'var(--color-primary)'
: 'var(--color-secondary)'
};
color: var(--text-color);
`;
// 主题注入
:root {
--color-primary: #3b82f6;
--text-color: #1f2937;
}
[data-theme="dark"] {
--color-primary: #60a5fa;
--text-color: #f9fafb;
}
效果立竿见影:
✅ 主题切换无闪烁(CSS变量实时生效)
✅ 样式作用域隔离,再也不怕“全局污染”
✅ TypeScript 能推导 $variant 类型,写错属性直接报错
更重要的是,产品迭代速度提升了40%。设计师甩来新配色,我只需要改几个CSS变量值,不用动一行业务逻辑。
场景二:企业级后台系统 → 别为了时髦硬上CSS-in-JS
今年三月,我入职一家跨境电商公司,负责内部ERP重构。团队8个人,项目周期6个月,UI极其稳定——基本就是表格、表单、图表三件套。
CTO问我:“要不要试试Linaria?听说零运行时开销。”
我差点就答应了。但冷静下来一想:这项目需要的是可维护性和团队协作效率,不是炫技。
于是我们坚持用SCSS + CSS Modules + PostCSS组合:
- 所有组件样式文件命名为
ComponentName.module.scss - 通过
composes复用基础样式 - 用
postcss-custom-properties支持CSS变量(用于换肤)
结果呢?三个月过去,代码库清爽得一批。新人第一天就能看懂样式结构,CI/CD构建速度比隔壁用Styled Components的团队快2倍(因为他们要处理JSX里的字符串拼接)。
最关键的是——没人半夜被“样式优先级地狱”吵醒。传统CSS在确定性场景下,依然是王者。
GitHub 上的真相:别被 hype 带跑偏
我特意去扒了几个明星项目的样式方案:
- Next.js 官方示例:混合使用(App Router 推荐 Tailwind,Pages Router 保留 CSS Modules)
- Material UI:JSS(已废弃)→ Emotion(当前)
- Ant Design:依然用 LESS,但提供 CSS-in-JS 实验性包
- Radix UI:纯 CSS,靠
data-*属性控制状态
发现没?没有哪个项目“一刀切”。就连最激进的Vercel,也在文档里写明:“如果你不需要动态主题或SSR优化,原生CSS完全够用”。
我甚至看到一个PR评论特别扎心:“We migrated to styled-components for ‘developer experience’, but now our bundle size increased by 120KB. Not worth it.”(我们为了“开发体验”迁移到styled-components,结果包体积涨了120KB,根本不值。)
我的综合选择指南:三问定乾坤
经过这半年的折腾,我总结出一套决策流程,分享给正在纠结的你:
1. 问产品形态
- To C、高频迭代、需要动态主题? → CSS-in-JS(Emotion / Styled Components)
- To B、UI稳定、团队规模大? → 传统CSS(SCSS + Modules)
2. 问技术约束
- 必须SSR? → 选支持 SSR 的 CSS-in-JS(如 Emotion)
- 极致性能敏感? → 避免运行时方案,用 Vanilla Extract 或 Linaria
- 团队抗拒学习成本? → 别硬推,用 PostCSS 插件渐进增强
3. 问长期维护
- 项目生命周期 > 2年? → 优先考虑社区活跃度(GitHub stars + issue响应速度)
- 需要和设计系统深度集成? → 看主流Design System用什么(比如Chakra UI绑定Emotion)
记住:技术选型不是选“最新”,而是选“最合适”。就像我和老婆异地,不是非要天天见面才叫爱情——合适的时间、合适的沟通方式,才是长久之道。
写在最后:Gap半年,我学会了“慢下来”
现在我的新工作稳定了,月薪24k(比裸辞前还高2k),每周五晚高铁去苏州,周日晚回杭州。生活节奏慢了,但思考更深了。
技术圈总在制造焦虑:“不用CSS-in-JS你就out了!”“Tailwind才是未来!” 可现实是——90%的项目,用传统CSS照样能做出优秀产品。
真正重要的,不是你用什么工具,而是你是否理解背后的权衡(trade-off)。就像我老婆说的:“你纠结样式方案的样子,像极了当初纠结要不要裸辞的我——其实答案早就在心里了,只是不敢承认。”
所以,别被 hype 带跑。打开你的项目,问问自己:
“我的用户需要什么?我的团队能承受什么?我的产品值得为这个技术买单吗?”
想清楚这三点,无论选CSS-in-JS还是传统CSS,你都不会错。
毕竟,代码是写给人看的——包括未来的你自己,和那个周末才能见面、却始终相信你的她。
P.S. 如果你也在Gap期焦虑,不妨fork我的样式方案对比仓库(虚构链接,别点),里面包含真实项目代码片段和性能测试数据。共勉。

评论 0