本指南将教您如何创建高性能 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 开发者工具和 Firefox 开发者工具提供许多工具,可帮助您弄清楚动画运行缓慢或出现故障的原因。
检查动画是否触发布局
使用 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
- 打开性能面板。
- 在动画播放时记录运行时性能。
- 检查 Summary 标签页。
如果您在 Summary 标签页中看到 Rendering 的非零值,可能表示您的动画让浏览器执行布局工作。
![“Summary”面板显示渲染用时 37 毫秒,绘制用时 79 毫秒。](https://web.developers.google.cn/static/articles/animations-guide/image/the-summary-panel-shows-3-d8a0efc73229b.jpg?authuser=5&hl=sv)
![“Summary”面板的渲染和绘制显示的值为零。](https://web.developers.google.cn/static/articles/animations-guide/image/the-summary-panel-show-ze-6036893c491f8.jpg?authuser=5&hl=sv)
Firefox 开发者工具
在 Firefox 开发者工具中,Waterfall 可以帮助您了解浏览器将时间花在何处。
- 打开性能面板。
- 在动画播放时开始录制性能。
- 停止录制并检查 Waterfall 标签页。
如果您看到重新计算样式的条目,则表示浏览器必须返回到呈现瀑布流的起始位置才能渲染动画。
检查是否存在丢帧
- 打开 Chrome 开发者工具中的渲染标签页。
- 选中 FPS 计量器复选框。
- 在动画运行时观察值。
请注意 FPS 计量器界面顶部的帧标签。
这会显示类似 50% 1 (938 m) dropped of 1878
的值。高性能动画的百分比较高(例如 99%
),这表示只有很少的帧丢失,并且动画看起来很流畅。
![fps 计量器显示有 50% 的帧丢失了](https://web.developers.google.cn/static/articles/animations-guide/image/the-fps-meter-shows-50-e279493d08c47.jpg?authuser=5&hl=sv)
![fps 计量器显示只有 1% 的帧丢失](https://web.developers.google.cn/static/articles/animations-guide/image/the-fps-meter-shows-1-97f98fe03092a.jpg?authuser=5&hl=sv)
检查动画是否触发绘制
浏览器在某些属性上绘制的开销要高于其他属性。例如,任何涉及模糊处理的内容(例如阴影)的绘制时间要比绘制红色框的时间长。在 CSS 中,这些差异并不总是很明显,但浏览器开发者工具可以帮助您确定需要重新绘制的区域,以及其他与绘制相关的性能问题。
Chrome DevTools
- 打开 Chrome 开发者工具中的渲染标签页。
- 选择 Paint Flashing。
- 在屏幕上移动指针。
![以绿色突出显示的界面元素,表示将会重新绘制](https://web.developers.google.cn/static/articles/animations-guide/image/a-ui-element-highlighted-43b56111254fb.jpg?authuser=5&hl=sv)
如果您看到整个屏幕闪烁,或者发现您认为不应更改的区域突出显示,请进一步调查。
如果您需要确定特定属性是否会导致与绘制相关的性能问题,可以使用 Chrome 开发者工具中的绘制性能分析器。
Firefox 开发者工具
- 打开 Settings,然后为 Toggle Paint flashing 添加 Toolbox 按钮。
- 在您要检查的页面上,开启该按钮,然后移动鼠标或滚动以查看突出显示的区域。
总结
请尽可能将动画限制为 opacity
和 transform
,以使动画保留在渲染路径的合成阶段。使用开发者工具检查路径的哪个阶段正受动画影响。
您可以使用绘制性能分析器查看任何绘制操作是否特别耗费资源。如果您发现任何信息,请检查其他 CSS 属性是否提供相同的外观和风格且性能更好。
请仅在遇到性能问题时谨慎使用 will-change
属性。