transition 对 position 变化无效,因 top/left 等布局属性不可插值,浏览器直接跳变;应改用 transform 或 opacity 等视觉层属性实现平滑过渡。

transition 为什么对 position 变化无效
直接给 position、top、left 加 transition,动画不会动——浏览器不把布局属性的突变当作可插值属性处理。它要么渲染旧位置,要么立刻跳到新位置,中间没有过渡帧。
常见错误现象:transition: top 0.3s 写了但毫无反应;元素在 display: none ↔ block 切换时闪现,不是淡入淡出。
- 真正能触发平滑过渡的,是「视觉层」属性:比如
opacity、transform、filter -
transform比top/left更高效(走 GPU 合成层),且天然支持插值 - 如果必须用
position控制初始布局,就别指望靠它做动画;把它当“定位锚点”,动画交给transform或opacity
opacity + transition 实现淡入淡出切换
这是最轻量、兼容性最好、也最容易踩坑的方案。关键不是加 opacity,而是控制它何时生效、何时可过渡。
使用场景:下拉菜单展开/收起、模态框显隐、Tab 面板切换。
立即学习“前端免费学习笔记(深入)”;
- 必须配合
visibility: hidden/visible使用,否则opacity: 0的元素仍占布局空间、可点击 -
transition要写在「稳定状态」上(比如默认状态),而不是只写在 hover 或 active 里 - 避免在
display: none和block之间切——display是离散属性,无法过渡,会打断opacity动画
示例:
div.panel {
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease, visibility 0.2s ease;
}
div.panel.active {
opacity: 1;
visibility: visible;
}
transform 替代 top/left 做位移过渡
想让元素从右往左滑入?或者从下往上浮起?别碰 top 和 bottom,用 transform: translateX() 或 translateY()。
性能影响:transform 触发合成层,不触发重排(reflow),比修改 top 快一个数量级。
- 初始偏移用
transform: translateX(100%),激活时设为translateX(0) - 注意:
transform不影响文档流,所以父容器不需要预留空间——这点和position: absolute类似,但更可控 - 多个方向同时动?写成
transform: translateX(-20px) translateY(-10px),不要拆成两个transition
错误示范:transition: top 0.3s, left 0.3s → 卡顿、跳帧;正确写法:transition: transform 0.3s ease
层级切换时 z-index 和 transition 的配合陷阱
z-index 本身不能过渡,但它的变化时机会影响你看到的“平滑感”。比如两个重叠弹窗快速切换,总感觉后出现的那个“压不住”前一个。
容易踩的坑:
-
z-index改变发生在opacity过渡开始前或结束后,导致视觉上“先透出再盖住”,产生错层感 - 没给所有参与切换的元素统一设置
position(至少是relative),z-index不生效 - 用 JavaScript 切换 class 时,
z-index和opacity不在同一个 tick 更新,浏览器可能合并渲染,造成竞态
实操建议:把 z-index 固定写死(比如 z-index: 10 和 z-index: 20),靠 class 控制显隐;需要动态管理时,用 requestAnimationFrame 手动分步更新 z-index 和 opacity。
复杂点在于:平滑感不是单靠 CSS 属性堆出来的,是 layout、paint、composite 三个阶段节奏对齐的结果。最容易被忽略的是——别在动画中触发重排。










