优先用 styled 处理带交互、需响应 props 或主题的组件,css 适合一次性静态样式;嵌套伪类需用对象语法或 styled;ssr 需服务端提取关键 css;与 tailwind 共用时注意插入顺序和 purgecss 配置。

Emotion 的 css 函数和 styled 用哪个?
css 返回的是类名字符串,适合动态样式或与非 Emotion 组件混用;styled 返回的是组件,自带 props 映射和主题透传能力。别在需要响应 props 变化的场景硬套 css,比如按钮的 disabled 状态切换——它不会自动重计算样式,得靠 useMemo 或手动管理,反而更重。
-
css适合:工具函数内生成一次性样式、搭配className手动注入、服务端渲染中避免组件层级过深 -
styled更适合:带交互逻辑的 UI 组件、需复用样式逻辑(如styled.button)、依赖主题变量的场景 - 注意
css不会做样式去重,高频调用可能产生冗余 class;styled内部做了哈希缓存,但每次调用新函数都会注册新组件(不要在 render 里定义styled.div)
为什么 css 里写 &:hover 没反应?
Emotion 默认不解析嵌套选择器,除非你显式启用 css 的插件支持,或者改用 styled。直接写 css<code>&:hover { color: red; } 在 v11+ 是无效的——它会被当成普通字符串,不触发编译。
- 正确做法是:用
styled包裹后写&:hover,或在css中用对象语法:css({ '&:hover': { color: 'red' } }) - 对象语法里不能用伪元素简写(如
::before要写成'&::before'),否则解析失败 - 如果用了 Babel 插件
@emotion/babel-plugin,模板字符串才支持嵌套,但该插件不兼容某些 monorepo 工具链(如 pnpm + changesets 场景下易漏编译)
SSR 下 Emotion 样式丢失或闪屏?
服务端渲染时,Emotion 需要同步提取并注入关键 CSS,否则客户端 hydration 后样式才加载,造成 FOUC。核心不是“有没有用 CacheProvider”,而是服务端是否把 extractCritical 或 renderStylesToString 的结果塞进了 HTML 的 <style></style> 标签里。
- Next.js 用户:确保使用
@emotion/server的renderStylesToString,并在getServerSideProps或getStaticProps中调用,把返回的styles注入到html字符串中 - Remix 用户:用
createEmotionCache配合CacheProvider,并在 root route 的headers中设置Content-Type: text/html,否则extractCritical可能拿不到完整样式树 - 常见坑:没清空服务端 cache 实例,导致多个请求共用一个 cache,样式互相污染;或客户端初始化
CacheProvider时用了不同 key,导致 hydrate 失败
Emotion 和 Tailwind 一起用会冲突吗?
不会全局冲突,但二者都操作 class 属性,叠加时容易覆盖或优先级错乱。比如 tw<code>text-red-500 和 css<code>color: blue 同时作用于一个元素,最终颜色取决于 CSS 特性(specificity)和插入顺序,而不是谁“更强”。
立即学习“前端免费学习笔记(深入)”;
- Emotion 的样式默认插入在
最前,Tailwind 的@layer规则通常靠后,所以纯 class 写法(如text-red-500)大概率被 Emotion 的内联样式覆盖 - 更稳妥的做法:用 Emotion 的
css封装 Tailwind 类名(css({ composes: 'text-red-500' })),或把 Tailwind 当作基础工具集,只用 Emotion 处理动态/条件逻辑部分 - 注意
css生成的 class 名含哈希,无法被 PurgeCSS 识别,若项目启用了 Tailwind 的 purge 功能,得在content配置里加*<em>/</em>.js,否则运行时样式被误删
Emotion 的性能开销藏在 cache 键的生成逻辑里,尤其是大量使用闭包函数作为样式参数时,哈希计算变慢,且容易让 React.memo 失效——这点很少被文档提,但线上 profile 时能看到明显差异。











