transition必须写在基础类中且始终存在,否则动画失效;需显式定义初始值,避免auto等不可计算值;禁用display等不可过渡属性,优先使用transform、max-height等可过渡方案。

transition没写在基础类里
浏览器需要从变化前就“看到”transition声明,否则直接跳变。常见错误是把transition塞进:hover、.active或JS切换的类里,比如:.btn.active { transition: opacity 0.3s; }——这样移出时transition已消失,自然没动画。
正确做法是把transition写死在基础类中:.btn { transition: opacity 0.3s, transform 0.2s; },状态类只管改值:.btn--disabled { opacity: 0.5; }。
用 DevTools 的 Computed 面板确认transition-property是否始终存在,而不是只在悬停或激活时才出现。
目标属性没有明确初始值
过渡需要可计算的起点。如果left、width、height等属性初始值是auto或未声明,第一次变化就会跳变。
例如:.slide { transition: left 0.4s; } + .slide--in { left: 100px; },但没写left: 0;,那第一次进入就是瞬移。
必须显式定义初始值:
.slide { left: 0; width: 100%; opacity: 1; transition: left 0.4s, width 0.4s, opacity 0.4s; }- 避免依赖默认值或继承,尤其是动态插入的 DOM 元素
- 用
getComputedStyle(el).left检查当前值是否为auto或initial
JS 切换 class 太快或顺序错
同步执行el.classList.remove("fade-out"); el.classList.add("fade-in");会导致transition声明被短暂清空,浏览器失去插值依据。
这不是 bug,是渲染机制:样式变更需经历 layout → paint → composite,中间若状态已变,过渡就被截断。
安全做法:
- 把
transition抽到一个永不移除的基础类里,如.animatable - 状态类只负责属性值,不带任何过渡声明
- 避免直接操作
el.style.opacity,它会覆盖 CSS 中的transition - 需要“闪一下”效果?用
requestAnimationFrame(() => el.classList.remove("flash"))
用了不可过渡的属性
display、height: auto、font-size(单位不一致时)、background-image(未显式声明)这些属性写了transition也无效,还不报错。
典型失效组合:
-
transition: height 0.3s;+height: auto;→ 完全不动 -
transition: all 0.3s;→ 某个不可过渡属性静默拖慢整体表现 -
visibility: hidden本身不可过渡,得配opacity: 0才看得见渐变
推荐替代方案:
- 高度展开:用
max-height: 0→max-height: 999px,并加overflow: hidden - 显隐控制:组合
opacity+pointer-events: none+visibility: hidden - 缩放/位移:优先用
transform,它是 GPU 加速且稳定支持的
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











