CSS-in-JS vs 传统CSS:一个成都应届生的样式方案血泪史

Spring打工人
2025-12-26 11:50
阅读 2309

去年十月,我刚拿到某大厂的 offer,坐标成都。HR 轻描淡写地说:“月薪 15k,含绩效。”
我心里一咯噔——房租 3500,吃饭 2000,交通 300,再扣掉五险一金和税,到手也就 11k 出头。这在北上广可能连合租都勉强,但在成都,至少还能活得像个人。

入职第一周,导师老张(真名保密)甩给我一个任务:“重构首页组件,用我们现在的样式方案,别整那些花里胡哨的。”

我打开代码库,满屏的 styled-componentsemotion,心里直打鼓:“这不是传说中的 CSS-in-JS 吗?我在校招面试时才背过概念,实操?零经验啊!”


那个让我通宵的周五晚上

事情真正崩盘是在上周五晚上。

我被安排优化一个商品卡片组件。原本是用原生 CSS 写的,但团队规范要求迁移到 CSS-in-JS。我心想:“不就是把 class 换成 JS 对象嘛,能有多难?”

结果,三小时过去,页面还是白的

问题出在哪?

  • 我用 styled.div 包裹了原本的 HTML 结构,但忘了 props 里传的动态颜色没生效。
  • 父组件用 className 传样式,子组件却用 css prop,两者根本对不上。
  • 更离谱的是,本地跑得好好的,一部署到测试环境,样式全乱了——因为构建工具没配好 CSS 提取插件。

凌晨一点,我瘫在出租屋的破沙发上,泡面凉了,女朋友发来消息:“今天又加班?你上周说好陪我看电影的……”
我回了个“嗯”,然后默默删掉第 8 次提交记录。

那一刻,我真的想砸键盘。


从“CSS 就是写 class”到“原来样式也能编程”

说实话,我本科那会儿学前端,老师教的是最传统的 CSS:

<div class="card">...</div>
.card {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

简单、直观、所见即所得。我甚至觉得,“前端不就该这样吗?搞那么多抽象干嘛?”

但进了大厂才发现,现实远比课堂复杂

我们的项目有上百个微前端子应用,共享一套 Design Token(设计变量)。产品经理今天说“主色换成深蓝”,明天说“按钮圆角调成 4px”。如果还用传统 CSS,光改变量就得搜遍几十个文件,还不提命名冲突、全局污染这些老毛病。

而 CSS-in-JS 的核心优势,就在这儿——样式即逻辑

比如用 emotion,你可以这么写:

import { css } from '@emotion/react'

const Card = ({ theme }) => (
  <div
    css={css`
      background: ${theme.bgColor};
      border-radius: ${theme.borderRadius};
      box-shadow: ${theme.shadow};
    `}
  >
    ...
  </div>
)

看出来了吗?样式直接绑定了 JavaScript 变量。主题切换?传个新 theme 对象就行。不需要维护 .scss 文件里的 $primary-color,也不用担心某个实习生手滑写了 .btn-primary { color: red !important; } 把全局搞崩。

这玩意儿,叫“可编程样式”。


但 CSS-in-JS 真的香吗?我的三个踩坑时刻

别急着吹。作为一个月薪 15k(后来涨到 22k,感谢年终奖)的应届生,我必须说:CSS-in-JS 不是银弹,它是一把双刃剑

踩坑 1:性能?别开玩笑

第一次代码 Review,老张指着我的 styled(Button) 说:“你这每渲染一次就生成一个新 class,知道 SSR 性能多差吗?”

我懵了。查资料才发现:CSS-in-JS 在服务端渲染时,会为每个组件实例生成唯一 class 名,并内联到 <style> 标签里。用户量一大,HTML 体积暴涨,首屏加载慢得像蜗牛。

解决方案?用 @emotion/cache + extractCritical 提取关键 CSS,或者干脆上运行时缓存。但这些配置,学校谁教过?

踩坑 2:调试?F12 都看不懂

有次线上样式错位,我打开 DevTools,看到的全是这种 class:

<div class="css-1a2b3c4">...</div>

点进去,样式长这样:

.css-1a2b3c4 {
  background-color: rgb(255, 255, 255) !important;
}

没有语义、没有层级、没有注释。想找哪个组件写的?只能靠猜。相比之下,传统 CSS 的 .product-card__title--highlight 至少还能看出点门道。

踩坑 3:学习成本?新人直接劝退

我们组来了个实习生,让他改个 hover 效果。他写:

const Button = styled.button`
  &:hover {
    color: blue;
  }
`

结果鼠标移上去没反应。
为什么?因为他父组件用了 React.memo,但 styled.button 每次都返回新组件,导致 memo 失效,hover 状态被重置。

这种“JS 闭包 + CSS 作用域 + React 渲染机制”的混合知识,不是背几个 API 就能搞定的。它要求你同时理解三套体系。


那传统 CSS 就过时了吗?别闹

吐槽归吐槽,我绝不否认传统 CSS 的价值。

最近我接了个内部工具项目,纯后台管理页,功能简单、迭代慢。我直接上 Tailwind + 原生 CSS Modules,开发速度飞快。为什么?

  • 无需编译.module.css 直接 import,class 自动哈希,不怕冲突。
  • DevTools 友好:审查元素能看到 .Card_title__abc123,至少知道是 Card 组件的 title。
  • 团队上手快:实习生三天就能独立开发,不用先啃一周 emotion 文档。

更别说那些老牌项目——比如公司 2016 年的老后台,还在用 jQuery + 全局 CSS。你敢动?动一下全站崩。这时候,稳定比时髦重要一万倍


我的选择:没有“最好”,只有“最合适”

经过这半年的折腾,我对样式方案的理解变了。

我不再问“CSS-in-JS 和传统 CSS 哪个更好”,而是问:“这个项目需要什么?”

场景 推荐方案 理由
大型产品、频繁主题切换、强组件化 CSS-in-JS (如 Emotion) 动态样式、作用域隔离、与 JS 逻辑深度集成
内部工具、静态页面、小团队 Tailwind + CSS Modules 开发快、调试直观、学习曲线平缓
遗留系统、低维护需求 原生 CSS / SCSS 稳定、兼容性好、改动风险低

上周,我又重构了一个组件。这次我没硬套 CSS-in-JS,而是根据需求拆解:

  • 公共布局 → 用 CSS Modules 写基础结构
  • 主题相关样式 → 用 useTheme() + emotion 动态注入
  • 交互反馈(hover/active)→ 保留在原生 CSS 伪类里

PR 一次性通过。老张居然夸我:“有进步,知道权衡了。”


代码人生,不止于技术选型

写这篇文的时候,我刚交完房租,3500,押一付三。银行卡余额不多,但心里踏实。

很多人说前端卷,样式方案三天一换,今天 Tailwind 明天 UnoCSS,后天又冒出什么原子化 CSS。作为应届生,很容易焦虑:“我是不是学错了?会不会被淘汰?”

但我想说:技术是工具,人才是核心

CSS-in-JS 或传统 CSS,本质上都是为了解决“如何高效、可靠地写样式”这个问题。纠结语法不如理解本质——

  • 你要解决命名冲突吗?→ 用作用域隔离(CSS Modules / styled-components)
  • 你需要动态主题吗?→ 用 JS 变量驱动样式(emotion / vanilla-extract)
  • 你追求极致性能吗?→ 用编译时方案(Linaria / Vanilla Extract)

真正的“代码人生”,不是追新,而是知道何时用什么,以及为什么用


最后一点真心话

如果你和我一样,是个刚入行的应届生,在成都拿着不算高但够活的工资,每天被各种技术方案搞得头大——
别慌

我去年十月还在为 flex-direction 写反了 debug 两小时,现在也能在 PR 里讨论 CSS-in-JS 的序列化策略了。成长从来不是一蹴而就,而是一次次踩坑、改错、反思堆出来的。

下次当你面对 styled.div.my-class 不知如何选择时,记住:
没有完美的方案,只有更合适的选择

而判断“合适”的能力,才是我们程序员真正的护城河。

(P.S. 上周终于陪女朋友看了《年会不能停!》,她说我黑眼圈重得像熊猫。看来,是时候优化下自己的“生活样式方案”了。)


教程彩蛋
想快速上手 CSS-in-JS?别死磕文档。

  1. 先用 create-react-app 起个项目
  2. npm install @emotion/react @emotion/styled
  3. 写一个带 props 的按钮,试试动态颜色
  4. 打开 DevTools,看看生成的 class 长啥样
  5. 再对比用 CSS Modules 实现同样的效果

亲自动手,比看十篇教程都管用。毕竟,代码人生,干就完了

评论 0

最热最新
暂无评论
Spring打工人Lv.1
0
影响力
0
文章
0
粉丝