本指南介绍了如何创建高性能 CSS 动画。
如需了解这些建议背后的理论,请参阅为什么某些动画运行缓慢?。
浏览器兼容性
本指南建议的所有 CSS 属性均具有良好的跨浏览器支持。
transform
opacity
will-change
移动元素
如需移动元素,请使用 transform
属性的 translate
或 rotation
关键字值。
例如,如需将项滑动到视图中,请使用 translate
。
.animate {
animation: slide-in 0.7s both;
}
@keyframes slide-in {
0% {
transform: translateY(-1000px);
}
100% {
transform: translateY(0);
}
}
使用 rotate
旋转元素。以下示例会将元素旋转 360 度。
.animate {
animation: rotate 0.7s ease-in-out both;
}
@keyframes rotate {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
调整元素大小
如需调整元素的大小,请使用 transform
属性的 scale
关键字值。
.animate {
animation: scale 1.5s both;
}
@keyframes scale {
50% {
transform: scale(0.5);
}
100% {
transform: scale(1);
}
}
更改元素的可见性
如需显示或隐藏某个元素,请使用 opacity
。
.animate {
animation: opacity 2.5s both;
}
@keyframes opacity {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
避免使用会触发布局或绘制的属性
在将任何 CSS 属性(transform
和 opacity
除外)用于动画之前,请先确定该属性对渲染流水线的影响。除非绝对必要,否则请避免使用任何会触发布局或绘制的属性。
强制创建图层
如为什么某些动画运行缓慢?中所述,将元素放在新层上可让浏览器重新绘制它们,而无需重新绘制布局的其余部分。
浏览器通常可以很好地决定应将哪些项放在新层上,但您也可以使用 will-change
属性手动强制创建层。顾名思义,此属性会告知浏览器此元素将以某种方式更改。
在 CSS 中,您可以将 will-change
应用于任何选择器:
body > .sidebar {
will-change: transform;
}
不过,规范建议您仅对始终即将更改的元素执行此操作。例如,对于用户可以滑入和滑出的边栏可能就是如此。对于不经常更改的元素,我们建议在可能发生更改时使用 JavaScript 应用 will-change
。请务必给浏览器足够的时间来执行必要的优化,并在更改停止后移除媒体资源。
如果您想在不支持 will-change
的浏览器(最有可能是 Internet Explorer)中强制创建图层,可以设置 transform: translateZ(0)
。
调试动画运行缓慢或出现故障的问题
Chrome DevTools 和 Firefox DevTools 提供了许多工具,可帮助您找出动画运行缓慢或出现故障的原因。
检查动画是否触发布局
如果动画使用 transform
以外的元素移动元素,则很可能会很慢。以下示例比较了使用 transform
的动画与使用 top
和 left
的动画。
.box { position: absolute; top: 10px; left: 10px; animation: move 3s ease infinite; } @keyframes move { 50% { top: calc(90vh - 160px); left: calc(90vw - 200px); } }
.box { position: absolute; top: 10px; left: 10px; animation: move 3s ease infinite; } @keyframes move { 50% { transform: translate(calc(90vw - 200px), calc(90vh - 160px)); } }
您可以在以下两个 Glitch 示例中对此进行测试,并使用开发者工具探索性能。
Chrome DevTools
- 打开效果面板。
- 在动画播放期间记录运行时性能。
- 检查摘要标签页。
如果您在摘要标签页中看到渲染的值不为零,则可能表示您的动画正在让浏览器执行布局工作。
Firefox 开发者工具
在 Firefox 开发者工具中,瀑布图可以帮助您了解浏览器在哪些方面花费了时间。
- 打开效果面板。
- 在动画播放期间开始录制性能数据。
- 停止录制并检查 Waterfall 标签页。
如果您看到 Recalculate Style 条目,则表示浏览器必须返回到渲染广告瀑布流的开头部分才能渲染动画。
检查是否存在丢帧
- 在 Chrome 开发者工具中打开渲染标签页。
- 选中 FPS 计量器复选框。
- 在动画运行时观察这些值。
请注意 FPS 计量器界面顶部的 Frames 标签。
系统会显示类似 50% 1 (938 m) dropped of 1878
的值。高性能动画的百分比较高(例如 99%
),这意味着只有很少的帧会被丢弃,并且动画看起来比较流畅。
检查动画是否会触发绘制
浏览器绘制某些属性的开销比其他属性要高。例如,绘制任何涉及模糊(例如阴影)的元素所花的时间将比绘制一个红框的时间要长。这些差异在 CSS 中并不总是显而易见,但浏览器开发者工具可以帮助您确定哪些区域需要重新绘制,以及其他与绘制相关的性能问题。
Chrome DevTools
- 在 Chrome 开发者工具中打开渲染标签页。
- 选择绘制闪烁。
- 在屏幕上移动指针。
如果您看到整个屏幕闪烁,或看到您认为不应发生变化的区域突出显示,请进一步调查。
如果您需要确定特定属性是否会导致与绘制相关的性能问题,Chrome 开发者工具中的绘制性能分析器可以派上用场。
Firefox 开发者工具
- 打开设置,然后为切换绘制闪烁添加 Toolbox 按钮。
- 在要检查的网页上,将该按钮切换到开启状态,然后移动鼠标或滚动屏幕即可查看突出显示的区域。
总结
请尽可能将动画限制为 opacity
和 transform
,以便将动画保留在渲染路径的合成阶段。使用 DevTools 检查路径的哪个阶段受到动画的影响。
使用绘制性能分析器查看是否有任何绘制操作开销特别大。如果发现任何问题,请检查是否可以使用其他 CSS 属性实现相同的外观和风格,同时获得更好的性能。
请谨慎使用 will-change
属性,仅在遇到性能问题时才使用。