合成层优化需精准触发:仅对满足transform/opacity动画、position:fixed、video等条件的元素创建合成层;滥用will-change或translateZ(0)会导致内存浪费和性能下降,应结合DevTools图层面板监控层数,优先控制在20层以内。
合成层优化不是加了 will-change 就万事大吉,多数卡顿问题反而因它而起。
浏览器只对满足特定条件的元素创建独立合成层:有 transform 或 opacity 动画、position: fixed、video、iframe,或显式设置了 will-change: transform / will-change: opacity。但注意:
will-change 是提示,不是指令——浏览器可能忽略,也可能提前分配资源;滥用会导致内存浪费甚至更慢transition: left 0.3s 不会进合成层,left 触发 layout → paint → composite 全流程,比 transform: translateX() 慢 3 倍以上transform: translateZ(0) 或 transform: scale(1) 强制分层,而非改 top/left
Chrome / Edge 开发者工具中打开 Layers 面板(需在 More Tools → Rendering 中勾选 “Layer borders” 和 “FPS meter”),滚动或触发动画后观察:
will-change 或冗余 transform
transform: translateZ(0) 和 will-change: transform 到底怎么选?两者目的都是触发合成层,但时机和可控性完全不同:
立即学习“前端免费学习笔记(深入)”;
translateZ(0) 是“硬触发”:只要样式生效,立刻建层,无条件,不回收;适合已知会长期动画的容器(如轮播外层 .carousel-wrapper)will-change 是“软提示”:告诉浏览器“接下来可能变”,浏览器决定是否建层、何时建、何时销毁;适合临时交互(如 hover 时放大按钮),但必须配合 JS 在交互结束后清除:element.style.willChange = 'auto'
.item)批量加 will-change —— 100 个 item 就可能生成 100 个图层,内存暴涨且毫无必要管用,但逻辑变了。合成层有自己的绘制顺序(paint order),z-index 只在**同一合成层内**生效;跨层时,由图层创建顺序和 transform-style 决定叠放关系:
transform-style: preserve-3d,子元素即使有 transform 也不会升层,z-index 仍按 DOM 顺序作用transform: translateZ(0) 到父容器),再用 z-index 调序真正难的是平衡——既要让动画跑在 GPU 上,又不能让图层数失控。很多团队调优到最后,删掉的 will-change 比加上的还多。