CSS-in-JS vs 传统CSS:一个裸辞半年程序员的样式方案选择指南
去年十月,我坐在老家县城那张吱呀作响的旧书桌前,盯着屏幕上闪烁的光标发呆。窗外是熟悉的南方小城秋日午后——阳光斜斜地洒在楼下的桂花树上,空气里飘着若有若无的甜香。而我的脑子里却乱成一团浆糊。
就在三个月前,我还在北京国贸附近某大厂“卷”得昏天黑地,月薪22k,房租3500块一个月租在回龙观的隔断间里。每天通勤两小时起步,回到家连饭都不想做,更别说写代码了。终于在一个加班到凌晨两点的周四晚上,我对着电脑屏幕上的需求文档,突然觉得:“老子不干了。”
于是,我裸辞了。
当时老婆还在视频里劝我:“你是不是冲动了?现在行情这么差……”
我说:“再干下去,我怕自己先猝死。”
她沉默了几秒,最后叹了口气:“那你回来吧,家里还有地方住。”
就这样,我带着笔记本和几件衣服,回到了这个生活成本几乎为零的小城。没有房租压力,吃饭每月开销不到1500,反而让我有了难得的喘息空间。但Gap期越长,焦虑就越重——尤其是看到朋友圈里前同事晒新offer、涨薪、升职的时候。
上周五晚上八点,我又投出去一份简历。这次是一家做企业级SaaS产品的创业公司,技术栈写着 React + SpringBoot + TypeScript。职位描述里赫然出现一句:“熟悉现代前端工程化,有CSS-in-JS或Tailwind经验者优先”。
我愣了一下。CSS-in-JS?这玩意儿我当然知道,但说实话,过去两年在大厂主要用的是传统的 CSS Modules + BEM 规范,偶尔配合 PostCSS 做些魔法。CSS-in-JS 虽然听说过 styled-components、Emotion 这些库,但总觉得“有点重”,而且团队里没人用,也就没深究。
可现在不一样了。面试官很可能拿这个当面试题来考你。
于是,我决定花一周时间,彻底搞清楚:到底什么时候该用 CSS-in-JS,什么时候坚持传统 CSS?
第一天:从“我觉得CSS-in-JS是噱头”开始
周日晚上十点,我泡了杯速溶咖啡(县城超市买不到手冲豆),打开 GitHub,搜了一堆热门开源项目。
- Vercel 的 Next.js 官方示例项目:大量使用 styled-jsx 和 Emotion
- Shopify 的 Polaris Design System:基于 CSS-in-JS 构建
- Ant Design:早期用 Less,后来部分组件支持 CSS-in-JS(v5 开始)
- 而像 Vue 生态里的 Element Plus,依然坚定走传统 SCSS 路线
有意思的是,我发现一个规律:越是强调“设计系统”、“主题切换”、“动态样式”的项目,越倾向 CSS-in-JS。
比如 Polaris,它允许开发者通过 props 动态改变按钮颜色、间距、圆角,甚至根据用户偏好自动切换深色/浅色模式。这种场景下,如果用传统 CSS,你得写一堆 .btn--theme-dark, .btn--size-large 这种类名,逻辑散落在 HTML 和 CSS 两个文件里,维护起来简直是灾难。
而用 Emotion,你可以这样写:
const Button = styled.button`
background: ${props => props.theme.primary};
border-radius: ${props => (props.rounded ? '999px' : '4px')};
padding: ${props => props.size === 'large' ? '16px' : '8px'};
`;
所有逻辑都在组件内部,一目了然。而且因为是 JavaScript 函数,还能做条件判断、调用工具函数,甚至接入 Redux 或 Context 获取全局状态。
那一刻,我突然意识到:CSS-in-JS 的核心优势,不是“把 CSS 写进 JS”,而是“让样式具备编程能力”。
第三天:传统 CSS 的反击
但别急着站队。周三下午,我在本地搭了个小型 SpringBoot 后台管理系统 demo(毕竟新岗位要对接 Java 后端),前端用 React + Ant Design Pro。
结果发现一个问题:首屏加载慢得离谱。
用 Lighthouse 测了一下,FCP(First Contentful Paint)高达 3.2 秒。查了下原因——Emotion 在 SSR 时会把所有动态样式注入 <style> 标签,导致 HTML 体积暴增。而我的页面其实很简单:一个表格,几个按钮,根本不需要那么复杂的动态样式。
我试着把 Ant Design Pro 的 CSS-in-JS 方案换成传统的 CSS Modules + 静态 SCSS,首屏直接降到 1.4 秒。
更关键的是,传统 CSS 在缓存和复用上天然占优。一个 global.css 文件可以被所有页面共享,浏览器缓存一次,后续请求直接命中。而 CSS-in-JS 的样式通常内联在 HTML 或 JS bundle 中,每次组件更新都可能生成新的 class 名(比如 css-1a2b3c),缓存利用率极低。
那天晚上,我和一个还在字节的朋友语音聊了会儿。他说他们内部现在也在“回滚”部分场景:“能用 Tailwind 或 CSS Modules 解决的,绝不碰 CSS-in-JS。除非要做 runtime theme switching,或者 micro-frontend 里隔离样式。”
第五天:Gemini 帮我理清思路
周五,我实在纠结,干脆打开 Google 新出的 Gemini(免费版),把问题扔给它:
“作为一个准备面试的前端工程师,如何向面试官解释 CSS-in-JS 和传统 CSS 的适用场景?”
Gemini 给了我一个结构清晰的回答,还附带对比表格(虽然有点模板化,但思路是对的)。我结合自己的实践,总结出以下决策树:
✅ 适合用 CSS-in-JS 的场景:
- 需要动态主题切换(如深色/浅色模式、多品牌定制)
- 组件高度封装,样式与逻辑强耦合(如 Design System)
- 项目规模小,追求开发体验 > 性能极致优化
- 团队已统一技术栈,且有成熟规范
✅ 适合用传统 CSS(或 CSS Modules / Tailwind)的场景:
- 静态页面、内容型网站(博客、官网、文档站)
- 性能敏感型应用(电商首页、Landing Page)
- 已有庞大 CSS 代码库,迁移成本高
- 后端主导的项目(比如 SpringBoot + Thymeleaf 渲染)
特别提醒:不要为了“时髦”而用 CSS-in-JS。我见过太多人把简单按钮写成 20 行 styled-component,结果 bundle size 翻倍,还拖慢 SSR。
面试实战:我把这段经历讲给了HR
昨天,我收到了那家创业公司的面试邀请。二面是技术负责人,四十岁左右,说话很直接。
他问:“我看你简历写熟悉 React,那你怎么处理组件样式?”
我没背八股文,而是说了实话:
“我之前在大厂主要用 CSS Modules + BEM,因为项目体量大,静态资源缓存很重要。但最近半年研究发现,CSS-in-JS 在动态性和开发体验上有优势,比如做主题切换时非常方便。不过我也做过实验,在简单页面上它反而拖慢首屏。所以现在我的原则是:按需选择,不迷信任何一种方案。”
他点点头:“很好,我们正好在做多租户 SaaS,每个客户要自定义 UI 主题,所以用了 Emotion。但后台管理页还是用的 Ant Design 的静态 CSS,因为不需要动态改。”
那一刻我知道,我答对了。
回望这半年:技术之外的成长
写这篇文章的时候,已经是深夜十一点。老婆刚发微信问我:“今天又学到新东西了?”
我说:“嗯,可能下周就能拿到 offer 了。”
她回了个笑脸:“那你明天记得去买菜,别又吃泡面。”
我笑了笑,关掉编辑器,望向窗外。这座小城没有霓虹灯,没有996,但给了我重新思考技术本质的空间。
裸辞不是逃避,而是为了找回对代码的热情。
Gap 不是躺平,而是蓄力后再出发。
这半年,我没刷 LeetCode,没背八股文,但我真正去理解了“为什么用这个技术”,而不是“别人用了所以我也用”。这种深度思考的能力,比任何框架 API 都重要。
给正在迷茫的你的建议
如果你也在犹豫要不要换工作、要不要学新技术,我的建议是:
- 先搞清楚“问题是什么”,再决定用什么工具。CSS-in-JS 不是银弹,传统 CSS 也没过时。
- 动手做对比实验。GitHub 上 fork 两个项目,测性能、看 bundle、读源码,比看一百篇博客都有用。
- 面试时讲真实经历。哪怕你说“我之前用错了,后来改了”,也比背标准答案强。
- 别被焦虑绑架。技术在变,但解决问题的思维不变。Springboot 写后端,React 写前端,底层逻辑都是“输入-处理-输出”。
最后,无论你选择哪种样式方案,记住:代码是写给人看的,顺便让机器执行。 样式也好,架构也罢,最终目标都是——让协作更顺畅,让用户更爽。
至于我?下周就要入职了,base 远程,月薪 24k(比裸辞前还高2k),而且不用交房租。
有时候,退一步,真的能看见更广阔的天空。
P.S. 如果你也在 Gap 期,不妨试试用一周时间深挖一个技术点。别贪多,就一个。搞懂了,面试就有底气。共勉。

评论 0