文档

文档

JavaScript

性能

性能

影响 Web 动画性能的主要因素有两个:渲染硬件加速

渲染是指获取 DOM 的更新并将其变化反映在屏幕上的过程。这会影响所有动画的性能。

硬件加速是指在主 JavaScript 线程之外运行动画的能力。这会影响与其他 JS 进程(如 React 渲染或其他数据密集型运算)同时运行的动画的性能。

让我们深入了解一下每个因素。

渲染

当我们更新元素的样式时

element.style.height = "500px"

浏览器需要通过重新渲染页面来反映此更改,即将 HTML 和 CSS 转换为在屏幕上显示的图像。

一般来说,浏览器渲染器执行此操作的步骤是

  1. 布局(Layout):计算页面上元素的大小和位置

  2. 绘制(Paint):将页面绘制到图形图层(layers)中 - 本质上是构成页面的各个图像

  3. 合成(Composite):将这些图层绘制到视口。

根据经验,工作量越少速度越快。

缓慢渲染

例如,如果我们更新一个元素的 height,这会改变元素的大小。更改元素的大小可能会影响兄弟元素或子元素的大小和/或位置,这本身可能会产生连锁反应,依此类推。因此,我们需要重新计算所有受影响元素的布局。

每当页面布局发生变化时,浏览器还需要重新绘制和重新合成受影响的图层。许多样式会影响布局,例如 heightborder-widthpaddingposition 等。

流畅的动画通常以每秒 60 帧 (fps) 的速度运行,与大多数屏幕刷新率相同。因此,如果我们想以 60fps 的速度更改元素的 height,我们需要能够在 16.7 毫秒内重新渲染。屏幕和浏览器越来越能够以 120fps 的速度进行动画处理,因此此时间窗口可以进一步缩短至 8 毫秒。

重新渲染很容易花费超过 100 毫秒!这就是为什么通常不鼓励动画布局的原因。
但是,这不是一成不变的规则。如果元素的布局是 изолированный 的,例如它具有 position: absolute 并且子元素很少,那么您或许可以流畅地对其进行动画处理。只需确保在低功耗设备上测试这些动画。

快速渲染

性能最佳的样式是那些仅触发第三个渲染步骤(合成器)的样式。
在所有现代浏览器中,transformopacity 将直接在图层上操作。因此,这些是在所有设备上进行动画处理的最安全的值。

浏览器也在此列表中添加更多值。例如,Chrome 和 Firefox 完全在合成器上处理 filter 和 SVG,而 Chrome 即将添加对 background-colorclip-path 的支持。

此外,由于 Motion 构建于 Web Animations API 之上,因此浏览器足够智能,可以自动将动画处理这些值的元素放置在新的图形图层上。

介于两者之间

还有许多值(如 box-shadowborder-radius)可以在不触发渲染的情况下更新,但确实需要可能代价高昂的绘制(步骤 2)。

您应始终在低功耗设备上测试这些属性的动画效果。

但是,仍然有一些方法可以提高这些动画的性能。

减小图层大小

首先,浏览器绘制图层所需的时间与图层的大小成正比。因此,您可以通过制作更小的图层来提高这些动画的性能。

您可以通过设置 willChange 来提示浏览器应该创建新图层样式"transform"

element.style.willChange = "transform"
animate(element, { borderRadius: "50%" })


创建新图层并非没有代价。每个图层都占用 GPU 上的空间。因此请谨慎使用。

使用替代样式

其次,您可以尝试用性能更好的替代样式替换样式。

我们已经看到浏览器正在改进对合成器上 filter 的支持。因此,与其动画处理 boxShadow,不如动画处理 filter使用drop-shadow函数:

// ❌
animate(element, { boxShadow: "10px 10px black" })

// ✅
animate(element, { filter: "drop-shadow(10px 10px black)" })


同样,浏览器正在将 clipPath 添加到合成器。因此,与其动画处理 borderRadius,不如动画处理 clipPath使用inset函数:

// ❌
animate(element, { borderRadius: "50px" })

// ✅
animate(element, { clipPath: "inset(0 round 50px)" })


哪个是哪个?

那么,您如何判断哪些样式会触发布局或绘制,哪些只会触发合成?

关于此主题的大多数教程都会推荐CSS Triggers。虽然这仍然是捕捉触发布局的样式(borderwidthtop)的好指南,但它已经非常过时,缺少有关 clip-pathfilter 的数据以及关于其他信息的过时信息。

浏览器一直在变化,因此最好的方法是在冒险使用 transformopacity 之外的样式时,进行跨浏览器和跨设备测试。每个浏览器都有性能分析工具,大多数浏览器都可以远程调试移动设备,因此请务必使用这些工具进行深入调查。

硬件加速

渲染性能应该是您首要关注的重点,因为这将是您制作的每个动画都需要考虑的因素。但还有动画过程本身的额外因素,以及它是否可以硬件加速。

动画最基本的形式是在一段时间内混合两个值。例如,如果我们想在一秒钟内从 "100px" 动画到 "200px",如果 0.5 秒已过,我们的动画将计算出 "150px"。这是一个非常简单的计算,与渲染相比,不会产生明显的开销。

但是,在浏览器中,我们可以通过多种方式计算此值

  • 使用 JavaScript,使用 requestAnimationFrame(如GSAPMotion)

  • 使用 Web Animations API(如 Motion)

  • 使用 CSS

JavaScript 代码始终在主 JS 线程上运行。这意味着如果您的应用程序同时运行其他 JS 代码,您的动画代码可能会被阻止运行。这将导致动画卡顿。

但是,WAAPI 和 CSS 可以在主 JS 线程之外,直接在合成器本身上运行某些动画。由于这通常是 GPU,因此通常称为硬件加速

硬件加速的动画将保持流畅,无论您的主 JS 线程变得多么繁忙。

由于 Motion 构建于 WAAPI 之上,因此它也可以运行硬件加速动画。

加速值

一般来说,如果样式仅调用合成渲染步骤,则理论上也可以对其进行动画处理。

transformopacity 是广泛支持的合成器样式,并且这些样式通常在合成器上进行动画处理。

其他值(如 filterbackground-colorclip-path 和 SVG)在大多数浏览器中要么已经支持,要么正在获得支持。

CSS 变量和 individual transforms

Motion 与 WAAPI 和 CSS 的独特之处在于,它支持 individual transforms 的动画处理

animate(".box", { x: 100, scale: 2 })

在底层,它正在动画处理 CSS 变量,但目前这些变量未加速,即使它们正在应用于 transform

因此,如果硬件加速在您的用例中至关重要,请坚持动画处理 transform

animate(".box", { transform: "translateX(100px) scale(2)" })

其他例外情况

即使在动画处理据称性能良好的样式时,每个浏览器对于动画是否获得加速都有不同的规则。

例如,直到最近,如果 Chrome 检测到像这样的基于 % 的 transform

animate(element, { transform: "translateX(100%)" })

不会进行硬件加速。

渐进增强

所有这些都表明,确保您的动画进行硬件加速可能是一个雷区。

我们建议将加速视为渐进增强。当浏览器支持它时,它很棒,但通常不是必需的。

如果您确实遇到来自繁忙 JavaScript 线程的大量卡顿,请坚持使用 transformfilterclipPathopacity

结论

为了实现流畅的动画,您的首要任务应该是您动画处理哪些值。作为开发人员,这是您可以最大程度控制的事情。

transformopacity 在所有浏览器中渲染成本最低。浏览器一直在改进其他样式(和 SVG)的渲染性能,filterbackground-colorclip-path 即将到来。

布局触发样式可以在不影响周围元素布局的元素上进行动画处理(例如,如果它们是 position: absolute)。但请确保在许多浏览器中,尤其是在低功耗设备中测试这些动画。

最后,如果您的网站在动画期间执行繁重的处理,硬件加速是避免卡顿的绝佳工具。但这不是您可以完全控制的东西,在许多情况下它会被禁用。

影响 Web 动画性能的主要因素有两个:渲染硬件加速

渲染是指获取 DOM 的更新并将其变化反映在屏幕上的过程。这会影响所有动画的性能。

硬件加速是指在主 JavaScript 线程之外运行动画的能力。这会影响与其他 JS 进程(如 React 渲染或其他数据密集型运算)同时运行的动画的性能。

让我们深入了解一下每个因素。

渲染

当我们更新元素的样式时

element.style.height = "500px"

浏览器需要通过重新渲染页面来反映此更改,即将 HTML 和 CSS 转换为在屏幕上显示的图像。

一般来说,浏览器渲染器执行此操作的步骤是

  1. 布局(Layout):计算页面上元素的大小和位置

  2. 绘制(Paint):将页面绘制到图形图层(layers)中 - 本质上是构成页面的各个图像

  3. 合成(Composite):将这些图层绘制到视口。

根据经验,工作量越少速度越快。

缓慢渲染

例如,如果我们更新一个元素的 height,这会改变元素的大小。更改元素的大小可能会影响兄弟元素或子元素的大小和/或位置,这本身可能会产生连锁反应,依此类推。因此,我们需要重新计算所有受影响元素的布局。

每当页面布局发生变化时,浏览器还需要重新绘制和重新合成受影响的图层。许多样式会影响布局,例如 heightborder-widthpaddingposition 等。

流畅的动画通常以每秒 60 帧 (fps) 的速度运行,与大多数屏幕刷新率相同。因此,如果我们想以 60fps 的速度更改元素的 height,我们需要能够在 16.7 毫秒内重新渲染。屏幕和浏览器越来越能够以 120fps 的速度进行动画处理,因此此时间窗口可以进一步缩短至 8 毫秒。

重新渲染很容易花费超过 100 毫秒!这就是为什么通常不鼓励动画布局的原因。
但是,这不是一成不变的规则。如果元素的布局是 изолированный 的,例如它具有 position: absolute 并且子元素很少,那么您或许可以流畅地对其进行动画处理。只需确保在低功耗设备上测试这些动画。

快速渲染

性能最佳的样式是那些仅触发第三个渲染步骤(合成器)的样式。
在所有现代浏览器中,transformopacity 将直接在图层上操作。因此,这些是在所有设备上进行动画处理的最安全的值。

浏览器也在此列表中添加更多值。例如,Chrome 和 Firefox 完全在合成器上处理 filter 和 SVG,而 Chrome 即将添加对 background-colorclip-path 的支持。

此外,由于 Motion 构建于 Web Animations API 之上,因此浏览器足够智能,可以自动将动画处理这些值的元素放置在新的图形图层上。

介于两者之间

还有许多值(如 box-shadowborder-radius)可以在不触发渲染的情况下更新,但确实需要可能代价高昂的绘制(步骤 2)。

您应始终在低功耗设备上测试这些属性的动画效果。

但是,仍然有一些方法可以提高这些动画的性能。

减小图层大小

首先,浏览器绘制图层所需的时间与图层的大小成正比。因此,您可以通过制作更小的图层来提高这些动画的性能。

您可以通过设置 willChange 来提示浏览器应该创建新图层样式"transform"

element.style.willChange = "transform"
animate(element, { borderRadius: "50%" })


创建新图层并非没有代价。每个图层都占用 GPU 上的空间。因此请谨慎使用。

使用替代样式

其次,您可以尝试用性能更好的替代样式替换样式。

我们已经看到浏览器正在改进对合成器上 filter 的支持。因此,与其动画处理 boxShadow,不如动画处理 filter使用drop-shadow函数:

// ❌
animate(element, { boxShadow: "10px 10px black" })

// ✅
animate(element, { filter: "drop-shadow(10px 10px black)" })


同样,浏览器正在将 clipPath 添加到合成器。因此,与其动画处理 borderRadius,不如动画处理 clipPath使用inset函数:

// ❌
animate(element, { borderRadius: "50px" })

// ✅
animate(element, { clipPath: "inset(0 round 50px)" })


哪个是哪个?

那么,您如何判断哪些样式会触发布局或绘制,哪些只会触发合成?

关于此主题的大多数教程都会推荐CSS Triggers。虽然这仍然是捕捉触发布局的样式(borderwidthtop)的好指南,但它已经非常过时,缺少有关 clip-pathfilter 的数据以及关于其他信息的过时信息。

浏览器一直在变化,因此最好的方法是在冒险使用 transformopacity 之外的样式时,进行跨浏览器和跨设备测试。每个浏览器都有性能分析工具,大多数浏览器都可以远程调试移动设备,因此请务必使用这些工具进行深入调查。

硬件加速

渲染性能应该是您首要关注的重点,因为这将是您制作的每个动画都需要考虑的因素。但还有动画过程本身的额外因素,以及它是否可以硬件加速。

动画最基本的形式是在一段时间内混合两个值。例如,如果我们想在一秒钟内从 "100px" 动画到 "200px",如果 0.5 秒已过,我们的动画将计算出 "150px"。这是一个非常简单的计算,与渲染相比,不会产生明显的开销。

但是,在浏览器中,我们可以通过多种方式计算此值

  • 使用 JavaScript,使用 requestAnimationFrame(如GSAPMotion)

  • 使用 Web Animations API(如 Motion)

  • 使用 CSS

JavaScript 代码始终在主 JS 线程上运行。这意味着如果您的应用程序同时运行其他 JS 代码,您的动画代码可能会被阻止运行。这将导致动画卡顿。

但是,WAAPI 和 CSS 可以在主 JS 线程之外,直接在合成器本身上运行某些动画。由于这通常是 GPU,因此通常称为硬件加速

硬件加速的动画将保持流畅,无论您的主 JS 线程变得多么繁忙。

由于 Motion 构建于 WAAPI 之上,因此它也可以运行硬件加速动画。

加速值

一般来说,如果样式仅调用合成渲染步骤,则理论上也可以对其进行动画处理。

transformopacity 是广泛支持的合成器样式,并且这些样式通常在合成器上进行动画处理。

其他值(如 filterbackground-colorclip-path 和 SVG)在大多数浏览器中要么已经支持,要么正在获得支持。

CSS 变量和 individual transforms

Motion 与 WAAPI 和 CSS 的独特之处在于,它支持 individual transforms 的动画处理

animate(".box", { x: 100, scale: 2 })

在底层,它正在动画处理 CSS 变量,但目前这些变量未加速,即使它们正在应用于 transform

因此,如果硬件加速在您的用例中至关重要,请坚持动画处理 transform

animate(".box", { transform: "translateX(100px) scale(2)" })

其他例外情况

即使在动画处理据称性能良好的样式时,每个浏览器对于动画是否获得加速都有不同的规则。

例如,直到最近,如果 Chrome 检测到像这样的基于 % 的 transform

animate(element, { transform: "translateX(100%)" })

不会进行硬件加速。

渐进增强

所有这些都表明,确保您的动画进行硬件加速可能是一个雷区。

我们建议将加速视为渐进增强。当浏览器支持它时,它很棒,但通常不是必需的。

如果您确实遇到来自繁忙 JavaScript 线程的大量卡顿,请坚持使用 transformfilterclipPathopacity

结论

为了实现流畅的动画,您的首要任务应该是您动画处理哪些值。作为开发人员,这是您可以最大程度控制的事情。

transformopacity 在所有浏览器中渲染成本最低。浏览器一直在改进其他样式(和 SVG)的渲染性能,filterbackground-colorclip-path 即将到来。

布局触发样式可以在不影响周围元素布局的元素上进行动画处理(例如,如果它们是 position: absolute)。但请确保在许多浏览器中,尤其是在低功耗设备中测试这些动画。

最后,如果您的网站在动画期间执行繁重的处理,硬件加速是避免卡顿的绝佳工具。但这不是您可以完全控制的东西,在许多情况下它会被禁用。

影响 Web 动画性能的主要因素有两个:渲染硬件加速

渲染是指获取 DOM 的更新并将其变化反映在屏幕上的过程。这会影响所有动画的性能。

硬件加速是指在主 JavaScript 线程之外运行动画的能力。这会影响与其他 JS 进程(如 React 渲染或其他数据密集型运算)同时运行的动画的性能。

让我们深入了解一下每个因素。

渲染

当我们更新元素的样式时

element.style.height = "500px"

浏览器需要通过重新渲染页面来反映此更改,即将 HTML 和 CSS 转换为在屏幕上显示的图像。

一般来说,浏览器渲染器执行此操作的步骤是

  1. 布局(Layout):计算页面上元素的大小和位置

  2. 绘制(Paint):将页面绘制到图形图层(layers)中 - 本质上是构成页面的各个图像

  3. 合成(Composite):将这些图层绘制到视口。

根据经验,工作量越少速度越快。

缓慢渲染

例如,如果我们更新一个元素的 height,这会改变元素的大小。更改元素的大小可能会影响兄弟元素或子元素的大小和/或位置,这本身可能会产生连锁反应,依此类推。因此,我们需要重新计算所有受影响元素的布局。

每当页面布局发生变化时,浏览器还需要重新绘制和重新合成受影响的图层。许多样式会影响布局,例如 heightborder-widthpaddingposition 等。

流畅的动画通常以每秒 60 帧 (fps) 的速度运行,与大多数屏幕刷新率相同。因此,如果我们想以 60fps 的速度更改元素的 height,我们需要能够在 16.7 毫秒内重新渲染。屏幕和浏览器越来越能够以 120fps 的速度进行动画处理,因此此时间窗口可以进一步缩短至 8 毫秒。

重新渲染很容易花费超过 100 毫秒!这就是为什么通常不鼓励动画布局的原因。
但是,这不是一成不变的规则。如果元素的布局是 изолированный 的,例如它具有 position: absolute 并且子元素很少,那么您或许可以流畅地对其进行动画处理。只需确保在低功耗设备上测试这些动画。

快速渲染

性能最佳的样式是那些仅触发第三个渲染步骤(合成器)的样式。
在所有现代浏览器中,transformopacity 将直接在图层上操作。因此,这些是在所有设备上进行动画处理的最安全的值。

浏览器也在此列表中添加更多值。例如,Chrome 和 Firefox 完全在合成器上处理 filter 和 SVG,而 Chrome 即将添加对 background-colorclip-path 的支持。

此外,由于 Motion 构建于 Web Animations API 之上,因此浏览器足够智能,可以自动将动画处理这些值的元素放置在新的图形图层上。

介于两者之间

还有许多值(如 box-shadowborder-radius)可以在不触发渲染的情况下更新,但确实需要可能代价高昂的绘制(步骤 2)。

您应始终在低功耗设备上测试这些属性的动画效果。

但是,仍然有一些方法可以提高这些动画的性能。

减小图层大小

首先,浏览器绘制图层所需的时间与图层的大小成正比。因此,您可以通过制作更小的图层来提高这些动画的性能。

您可以通过设置 willChange 来提示浏览器应该创建新图层样式"transform"

element.style.willChange = "transform"
animate(element, { borderRadius: "50%" })


创建新图层并非没有代价。每个图层都占用 GPU 上的空间。因此请谨慎使用。

使用替代样式

其次,您可以尝试用性能更好的替代样式替换样式。

我们已经看到浏览器正在改进对合成器上 filter 的支持。因此,与其动画处理 boxShadow,不如动画处理 filter使用drop-shadow函数:

// ❌
animate(element, { boxShadow: "10px 10px black" })

// ✅
animate(element, { filter: "drop-shadow(10px 10px black)" })


同样,浏览器正在将 clipPath 添加到合成器。因此,与其动画处理 borderRadius,不如动画处理 clipPath使用inset函数:

// ❌
animate(element, { borderRadius: "50px" })

// ✅
animate(element, { clipPath: "inset(0 round 50px)" })


哪个是哪个?

那么,您如何判断哪些样式会触发布局或绘制,哪些只会触发合成?

关于此主题的大多数教程都会推荐CSS Triggers。虽然这仍然是捕捉触发布局的样式(borderwidthtop)的好指南,但它已经非常过时,缺少有关 clip-pathfilter 的数据以及关于其他信息的过时信息。

浏览器一直在变化,因此最好的方法是在冒险使用 transformopacity 之外的样式时,进行跨浏览器和跨设备测试。每个浏览器都有性能分析工具,大多数浏览器都可以远程调试移动设备,因此请务必使用这些工具进行深入调查。

硬件加速

渲染性能应该是您首要关注的重点,因为这将是您制作的每个动画都需要考虑的因素。但还有动画过程本身的额外因素,以及它是否可以硬件加速。

动画最基本的形式是在一段时间内混合两个值。例如,如果我们想在一秒钟内从 "100px" 动画到 "200px",如果 0.5 秒已过,我们的动画将计算出 "150px"。这是一个非常简单的计算,与渲染相比,不会产生明显的开销。

但是,在浏览器中,我们可以通过多种方式计算此值

  • 使用 JavaScript,使用 requestAnimationFrame(如GSAPMotion)

  • 使用 Web Animations API(如 Motion)

  • 使用 CSS

JavaScript 代码始终在主 JS 线程上运行。这意味着如果您的应用程序同时运行其他 JS 代码,您的动画代码可能会被阻止运行。这将导致动画卡顿。

但是,WAAPI 和 CSS 可以在主 JS 线程之外,直接在合成器本身上运行某些动画。由于这通常是 GPU,因此通常称为硬件加速

硬件加速的动画将保持流畅,无论您的主 JS 线程变得多么繁忙。

由于 Motion 构建于 WAAPI 之上,因此它也可以运行硬件加速动画。

加速值

一般来说,如果样式仅调用合成渲染步骤,则理论上也可以对其进行动画处理。

transformopacity 是广泛支持的合成器样式,并且这些样式通常在合成器上进行动画处理。

其他值(如 filterbackground-colorclip-path 和 SVG)在大多数浏览器中要么已经支持,要么正在获得支持。

CSS 变量和 individual transforms

Motion 与 WAAPI 和 CSS 的独特之处在于,它支持 individual transforms 的动画处理

animate(".box", { x: 100, scale: 2 })

在底层,它正在动画处理 CSS 变量,但目前这些变量未加速,即使它们正在应用于 transform

因此,如果硬件加速在您的用例中至关重要,请坚持动画处理 transform

animate(".box", { transform: "translateX(100px) scale(2)" })

其他例外情况

即使在动画处理据称性能良好的样式时,每个浏览器对于动画是否获得加速都有不同的规则。

例如,直到最近,如果 Chrome 检测到像这样的基于 % 的 transform

animate(element, { transform: "translateX(100%)" })

不会进行硬件加速。

渐进增强

所有这些都表明,确保您的动画进行硬件加速可能是一个雷区。

我们建议将加速视为渐进增强。当浏览器支持它时,它很棒,但通常不是必需的。

如果您确实遇到来自繁忙 JavaScript 线程的大量卡顿,请坚持使用 transformfilterclipPathopacity

结论

为了实现流畅的动画,您的首要任务应该是您动画处理哪些值。作为开发人员,这是您可以最大程度控制的事情。

transformopacity 在所有浏览器中渲染成本最低。浏览器一直在改进其他样式(和 SVG)的渲染性能,filterbackground-colorclip-path 即将到来。

布局触发样式可以在不影响周围元素布局的元素上进行动画处理(例如,如果它们是 position: absolute)。但请确保在许多浏览器中,尤其是在低功耗设备中测试这些动画。

最后,如果您的网站在动画期间执行繁重的处理,硬件加速是避免卡顿的绝佳工具。但这不是您可以完全控制的东西,在许多情况下它会被禁用。

保持关注

订阅以获取最新消息和更新。

©2025 Motion Division Ltd.
保持关注

订阅以获取最新消息和更新。

©2025 Motion Division Ltd.