直接原因是动画中修改了触发layout和paint的css属性,导致浏览器每帧重算布局、重绘图层,全部压在主线程;应改用transform等合成属性并合理使用will-change和visibilitychange监听来优化。

直接原因:动画中修改了会强制触发 Layout 和 Paint 的 CSS 属性,浏览器每帧都得重算布局、重绘图层,全部压在主线程上跑。
哪些 CSS 属性一动就拉高 CPU
只要在 @keyframes 或 transition 里改这些,基本等于主动邀请 CPU 过载:
-
width/height/max-width/min-height -
top/bottom/left/right(配合position: relative或absolute) -
margin/padding/border-width -
display/float/clear -
font-size/line-height(影响行盒尺寸,间接触发布局)
它们的共同点是:浏览器无法跳过 Layout 阶段——哪怕只改 1px,也得重新计算整个渲染树。
怎么快速验证是不是 layout/paint 拖垮了帧率
打开 Chrome DevTools → Performance 面板 → 录制一段动画 → 看火焰图里 Layout 和 Paint 是否密集出现。如果这两项占满每帧时间线,问题就坐实了。
- 对比看:
transform: translateX(100px)的帧里只有Composite Layers;而left: 100px的帧里 Layout + Paint 占据大半 - 注意 Safari 和旧版 Firefox 更敏感,同样写法下 CPU 升幅可能比 Chrome 高出 2–3 倍
替换成安全属性的具体操作
不改逻辑,只换属性,就能绕开 Layout/Paint:
- 把
left: 100px改成transform: translateX(100px) - 把
top: 50px改成transform: translateY(50px) - 把
width: 200px改成transform: scaleX(2),并加transform-origin: left center控制缩放起点 - 避免在同一个元素上叠加
box-shadow+background: linear-gradient+ 动画——Paint 开销会指数级上升
别迷信 translate3d(0, 0, 0),它确实能升层,但滥用会让图层数失控,内存占用飙升。优先用 will-change: transform,且必须在动画开始前 1–2 帧动态加上,结束立即移除。
隐藏页标签里动画还在狂飙 CPU?那大概率不是 CSS 动画
CSS 动画(纯 @keyframes 或 transition)在标签页隐藏时,浏览器会自动暂停合成线程,CPU 几乎为 0。如果你发现隐藏后 CPU 仍高,说明实际在跑的是 requestAnimationFrame 回调。
-
requestAnimationFrame不感知页面可见性,只要没手动cancelAnimationFrame,JS 线程就照常每秒调 60 次 - Safari 和部分安卓 WebView 完全不节流后台 tab,
getBoundingClientRect()这类同步布局 API 在里面每调一次,都等于主动触发一次 Layout - 正确做法:监听
visibilitychange,切后台时cancelAnimationFrame,切回前台再requestAnimationFrame,且要加状态锁防抖
真正容易被忽略的是:用 element.animate() 启动的动画返回的是 Animation 对象,它不会随页面隐藏自动暂停,必须显式调用 animation.pause()。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











