加了transition却没动画,根本原因是三个条件未同时满足:transition必须写在基础样式中而非状态类里;属性必须可插值且起止值明确(如opacity、transform可行,display或height:auto不可行);JS修改样式后需强制重排(如void el.offsetWidth)以让浏览器捕获旧值。

页面切换过渡效果不会自动生效,必须手动控制 DOM 状态 + 显式声明可动画属性,否则加了 transition 也白搭。
为什么加了 transition 却没动画?
常见现象是 JS 切换 class 后元素“啪”一下就变了,没有渐变过程。这不是浏览器不支持,而是三个条件没同时满足:
-
transition必须写在基础样式里(比如body、.page),不能只放在.dark或.active类中;否则默认状态无过渡规则,第一次切换就是硬跳 - 目标属性必须可插值且起止值明确——
opacity、transform行,display、height: auto、visibility不行 - JS 修改样式后,浏览器需要一次重排机会来“记住”旧值;直接
el.classList.add('fade-in')就走下一步,动画会被合并跳过
补救方法:加一句 void el.offsetWidth 强制同步读取布局,再设新类。
用 transform/opacity 做内容切换最稳
比起改 display 或 visibility,用位移+透明度组合既能避免重排,又能走 GPU 合成层,性能好、兼容性强。
立即学习“前端免费学习笔记(深入)”;
- 给所有页面容器统一设
position: absolute; top: 0; left: 0; width: 100%; height: 100% - 初始状态:当前页
transform: translateX(0); opacity: 1,目标页transform: translateX(100%); opacity: 0 - 切换时先更新目标页
transform: translateX(0); opacity: 1,再更新当前页transform: translateX(-100%) - iOS Safari 上建议加
will-change: transform, opacity防闪烁
View Transitions API 动画消失的常见原因
这个 API 不是 transition 的替代品,它靠浏览器拍快照合成动画帧,对 DOM 状态非常敏感。
-
document.startViewTransition()必须包裹**同步 DOM 更新操作**,比如container.replaceChildren(newNode);里面塞await fetch()或setTimeout就失效 - 新旧元素都必须带完全一致的
view-transition-name(大小写、空格、动态 ID 全部算错) - 旧元素在过渡开始前不能是
display: none或opacity: 0;哪怕opacity: 0.001也能被快照捕获 - 检查 DevTools → Layers 面板,若没看到
::view-transition-old图层,基本就是 name 没对上或旧元素不可见
history.pushState 后如何手动触发入场动画
路由切换不刷新页面,DOM 没重建,浏览器认为“元素一直在这”,光加类名不会触发 transition。
- fetch 新内容后,先插入容器但保持隐藏态:
newEl.style.opacity = '0'; newEl.style.transform = 'translateY(20px)' - 立刻读一个布局属性(如
container.scrollHeight)强制重排 - 再添加动画类(如
animate-in),让浏览器感知到变化 - 监听
transitionend时注意过滤属性名:if (e.propertyName === 'transform'),避免opacity和transform触发两次事件导致清理过早
最容易被忽略的是“可绘制状态”——很多动画失效,不是代码写错,而是旧元素在快照前已被设为不可见,或者新元素还没 append 到 document 就设置了 view-transition-name。



















