transition 必须写在步骤项基础类(如.step)中,配合js强制重排(offsetheight)和仅过渡opacity/transform,才能实现双向平滑切换。

步骤条切换加 transition 本身不生效,必须配合 JS 控制状态 + CSS 显式声明可过渡属性,且不能依赖 display 切换或 class 增删本身触发动画。
transition 写在步骤项基础样式里,不是 :active 或 .active 中
常见错误是把 transition 只写在 .step.active 里,结果只有“激活”时有动画,“取消激活”时直接跳变。浏览器不会为离开的 class 自动补过渡。
- 正确做法:把
transition放在所有步骤项共用的基础类中,比如.step - 必须给每个步骤项定义明确的初始态,例如
opacity: 0.6、transform: scale(0.95),而不是靠display: none或未声明值“默认隐藏” - 如果用
visibility: hidden配合opacity,要确保visibility不参与过渡(它不可动画化),只靠opacity和transform实现视觉切换
只过渡 transform 和 opacity,别碰 width/height/left/top
步骤条常被误操作:给 .step 加 transition: width 0.3s 或通过 left 移动当前高亮位置——这些会触发重排,滚动卡顿、动画掉帧在中低端设备上非常明显。
- 安全组合:
transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1), transform 0.25s cubic-bezier(0.4, 0, 0.2, 1) - 高亮当前步:用
transform: scale(1.05) translateY(-2px)替代border-bottom: 2px solid #4A90E2,后者可能引发重绘抖动 - 禁用
transition: all—— 它会偷偷监听font-size、padding等变化,尤其当步骤文字随状态微调时,动画节奏全乱
JS 切换步骤时,必须强制重排再应用新状态
用 element.classList.toggle('active') 后动画一闪而过,甚至不播,是因为浏览器把 DOM 更新和样式变更合并渲染,没机会捕获“起始帧”。
- 修复方式:在切换 class 前,读一次布局属性,例如
void stepElement.offsetHeight - 完整顺序示例:
currentStep.classList.remove('active'); void currentStep.offsetHeight; // 强制重排,固化旧态 nextStep.classList.add('active'); - 如果步骤条是动态生成(如从 API 渲染),确保所有
.step元素已挂载到 DOM 再执行上述逻辑,否则offsetHeight返回 0,重排无效
多步骤并行过渡时,transitionend 事件要过滤属性名
一个步骤项同时过渡 opacity 和 transform,transitionend 会触发两次。若你在回调里直接移除动画类或更新状态,大概率只处理了一半,导致下一次切换错位。
- 监听时加判断:
if (e.propertyName === 'transform')或if (e.propertyName === 'opacity') - 更稳妥的做法:统一设相同时长(如都用
0.25s),然后用setTimeout(() => { /* 清理 */ }, 250)替代事件监听,避开竞态 - 注意事件冒泡:步骤条容器若也监听
transitionend,需用e.stopPropagation(),否则子项触发会层层上报
真正难的不是写对那几行 transition,而是每一步状态切换都得确保:浏览器能识别“值变了”,且这个变化发生在独立渲染帧里。漏掉 offsetHeight、写错基础样式位置、或者让 display 参与流程,都会让整个过渡静默失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











