在前端页面开发中,元素位移是最常见的基础动效需求之一,开发者通常会选择使用CSS的transform属性或者position相关属性来实现位移效果,但两者的性能表现存在明显差异,选择不当可能会导致页面卡顿、渲染效率下降等问题。

两种位移方式的基础用法
position实现位移
使用position实现位移通常需要配合top、right、bottom、left四个属性,通过改变元素的位置值来完成移动,常见的定位类型包括relative、absolute、fixed。
/* position相对定位位移示例 */
.position-box {
position: relative;
/* 向右位移100px,向下位移50px */
left: 100px;
top: 50px;
}
transform实现位移
transform属性通过translate函数实现位移,支持translateX、translateY、translateZ等方向控制,也可以直接写translate(x, y)同时设置两个方向的位移。
/* transform位移示例 */
.transform-box {
/* 向右位移100px,向下位移50px */
transform: translate(100px, 50px);
}
性能差异的核心原因
要理解两者的性能差异,需要先了解浏览器的渲染流程,主要分为以下步骤:
- 解析HTML生成DOM树,解析CSS生成CSSOM树
- 合并DOM和CSSOM生成渲染树
- 计算渲染树中每个节点的布局信息,这一步称为重排(Reflow)
- 将渲染树的每个节点绘制到屏幕,这一步称为重绘(Repaint)
- 将绘制结果合成到最终屏幕显示,这一步称为合成(Composite)
position位移的渲染影响
使用position改变left、top等属性时,会直接修改元素的布局信息,触发浏览器的重排操作。重排会重新计算所有受影响元素的几何位置,范围可能覆盖整个页面或者局部大量节点,计算成本很高。重排之后必然触发重绘,将新的布局结果绘制到屏幕,整体渲染开销较大。
如果是在动画场景下频繁修改position的位移属性,每一帧都会触发重排重绘,很容易导致动画帧率下降,出现卡顿现象。
transform位移的渲染影响
transform属性的位移操作不会修改元素的布局信息,不会触发重排,只会触发合成阶段的操作。现代浏览器会对transform属性做优化,当元素应用了transform位移时,浏览器会将该元素提升到独立的合成层,位移操作直接由GPU处理,不需要CPU参与布局计算和重绘,渲染开销极低。
在动画场景下使用transform位移,每一帧只需要更新合成层的变换矩阵,不会触发重排重绘,能够轻松保持60fps的流畅动画效果。
性能对比测试
我们可以通过简单的动画示例对比两种方式的性能表现,测试在1秒内让元素移动1000px的动画效果。
position动画示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
.pos-box {
position: relative;
width: 100px;
height: 100px;
background: #409eff;
/* 使用position实现位移动画 */
animation: posMove 1s linear infinite;
}
@keyframes posMove {
from { left: 0; }
to { left: 1000px; }
}
</style>
</head>
<body>
<div class="pos-box"></div>
</body>
</html>
transform动画示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
.tf-box {
width: 100px;
height: 100px;
background: #67c23a;
/* 使用transform实现位移动画 */
animation: tfMove 1s linear infinite;
}
@keyframes tfMove {
from { transform: translateX(0); }
to { transform: translateX(1000px); }
}
</style>
</head>
<body>
<div class="tf-box"></div>
</body>
</html>
通过浏览器的Performance面板录制动画过程可以发现,position动画会频繁出现Layout(重排)和Paint(重绘)的标记,而transform动画只会出现Composite(合成)的标记,前者的主线程占用时间远高于后者。
适用场景建议
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 需要频繁更新的位移动画 | transform | 不会触发重排重绘,GPU加速性能更好,动画更流畅 |
| 静态布局的元素初始定位 | position | 只触发一次布局计算,性能差异可以忽略,符合布局语义 |
| 需要脱离文档流的定位 | position | absolute、fixed等定位方式本身就需要position属性,位移是定位的附带效果 |
| 3D空间位移 | transform | 支持translateZ属性,配合perspective可以实现3D位移效果,position不支持Z轴位移 |
注意事项
- transform位移不会改变元素在文档流中的原始位置,不会影响其他元素的布局,而position的relative位移会保留元素原位置,absolute和fixed位移会脱离文档流
- 过度使用transform提升合成层也可能导致内存占用过高,不要在页面中给大量元素无必要地添加transform属性
- 如果需要兼容非常老旧的浏览器,需要测试transform的兼容性,不过现代浏览器基本都支持transform属性
总结来说,在需要实现动态位移、尤其是动画场景时,优先选择transform属性可以获得更好的性能表现,而静态布局或者需要脱离文档流的定位场景,使用position更符合开发逻辑,开发者可以根据实际需求灵活选择。