CSS-in-JS动画性能差的主因是运行时动态增删@keyframes触发CSSOM重解析;styled-components频繁挂载/卸载导致规则反复注入,emotion虽内联但仍有哈希冗余和SSR不一致问题;外部CSS文件可彻底规避动态操作,适合逻辑固定的高频动画。

CSS-in-JS 方案本身不必然导致动画性能差,真正拖慢渲染的,是它在运行时动态注入 @keyframes 规则的方式 —— 尤其当组件高频挂载/卸载、或大量实例共存时,样式表反复增删会触发浏览器重解析 CSSOM,间接影响合成线程调度。
为什么 styled-components 的 keyframes 注入会引发性能抖动
styled-components 的 keyframes 函数每次调用都会生成新哈希名,并通过 document.styleSheets 动态插入一条规则。这不是“一次性注册”,而是:组件挂载 → 插入规则 → 组件卸载 → 删除规则 → 再挂载 → 再插入……
这个过程在以下场景中明显暴露问题:
- 列表项使用带动画的
Box组件(如卡片入场),滚动时频繁触发 mount/unmount - 路由切换带过渡动画的页面,多个
keyframes被快速增删 - 服务端渲染(SSR)后客户端水合(hydration)阶段,样式表状态不一致,导致重复注入
浏览器对 styleSheet.insertRule() 和 deleteRule() 的调用并不轻量,尤其在低端 Android 设备上,单次插入可能引发微卡顿。
emotion 的 css + keyframes 为何更稳但仍有隐患
emotion 的 keyframes 返回纯 CSS 字符串,配合 css 函数可直接内联到元素 style 属性(如 animationName: 'a1b2c3'),绕过样式表操作 —— 这看似规避了注入开销,但带来新问题:
- 动画名仍需全局唯一,emotion 会自动哈希,但若同一动画被多处引用,可能生成多个冗余规则
-
css块中嵌套keyframes时,若父组件 props 变化导致整个css重新计算,keyframes字符串也会重生成,即使内容未变 - SSR 场景下,服务端生成的 keyframes 名与客户端不一致,首次渲染动画可能丢失(需启用
cache配置并透传 nonce)
换句话说:不是“不操作样式表”,而是把操作时机从组件生命周期挪到了样式计算路径上,压力仍在。
用外部 .css 文件定义 keyframes 的真实收益
把 @keyframes 提到独立 CSS 文件里,本质是把动画规则从“运行时动态管理”降级为“构建时静态声明”。这带来的改变很实在:
- 浏览器只在首次加载时解析一次
@keyframes,后续所有animation-name引用都走内部符号查找,零开销 - 无需 JS 参与注入/清理,彻底避开
styleSheetAPI 的同步阻塞风险 - 支持预加载(
<link rel="preload" as="style">)和 HTTP 缓存,首屏动画更快触达 - 关键帧可被 PurgeCSS 等工具识别并保留(只要你在 JS 中显式引用类名),不会误删
示例:你写一个 animations.css,里面只有:
@keyframes fade-in-up {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
然后在组件中直接用 class 或 emotion 的 css 引用:animation: fade-in-up 0.3s ease-out; —— 名字写死,浏览器秒认。
什么时候不该切到外部 CSS
外部 CSS 失去的是“动态参数能力”。如果你的动画必须依赖组件 props 实时算出偏移量、颜色、持续时间等,比如:
transform: translateY(${props => props.offset}px)background: ${props => props.theme.accent};
那硬塞进外部 CSS 就得靠 CSS 变量(var(--offset))桥接,而变量值仍需 JS 注入到 :root 或元素 style 上 —— 此时性能瓶颈又回到 JS 操作本身。这种 case,不如老实用 CSS-in-JS,但要控制 keyframes 定义粒度(例如每个动画只定义一次,用 useMemo 缓存)。
真正该切的,是那些「逻辑固定、仅需复用」的动画:loading 转圈、按钮点击反馈、模态框淡入、卡片滑入……它们不需要运行时插值,却承担着高频调用压力 —— 这部分才是外部 CSS 能稳住的关键战场。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











