加了 transition 却没动画,是因为起始值未声明、DOM 更新被合并或属性不可过渡;transition 必须写在基础类中,初始值需显式设置,避免 transition: all,JS 切换 class 前需强制重排,View Transitions API 仅适用于同步 DOM 更新且新旧元素 view-transition-name 必须完全一致。

加了 transition 却没动画,大概率是起始值没声明、DOM 更新被合并、或属性根本不可过渡——不是浏览器不支持,而是触发条件没凑齐。
transition 写在哪?必须写在基础类里,不能只放 .active 中
常见错误是把 transition: opacity 0.3s 只写在 .page.active 里。结果只有“变亮”有动画,“变暗”直接跳变。浏览器不会为离开的 class 补过渡。
正确做法:把过渡规则放在所有状态共用的基础选择器中,比如:
section.page {
opacity: 0;
transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1), transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
section.page.active {
opacity: 1;
transform: translateY(0);
}
- 初始值(
opacity: 0、transform: translateY(20px))必须显式写出,不能靠“默认”或display: none隐藏 - 避免
transition: all—— 它会监听padding、font-size等变化,一旦 JS 微调文字大小,动画节奏就乱 - 如果用 CSS 变量控制颜色或尺寸,确保明/暗两端都赋了具体值,否则插值失效
JS 切换 class 后动画一闪而过?缺一次强制重排
element.classList.add('active') 后动画不播,是因为浏览器把 DOM 更新和样式计算合并成一帧,没机会捕获“起始态”。
立即学习“前端免费学习笔记(深入)”;
修复很简单:在改 class 前,读一次布局属性,比如:
currentSection.classList.remove('active');
void currentSection.offsetHeight; // 强制重排,固化旧态
nextSection.classList.add('active');
- 必须在
remove和add之间加这句,顺序不能反 - 如果页面是动态渲染(如 API 拉取后
insertAdjacentHTML),确保元素已挂载到 DOM 再执行,否则offsetHeight返回 0 - 不要用
setTimeout替代——它不可靠,缩放设置、GPU 就绪延迟都会导致偏差
用 View Transitions API?先确认它适用场景
这个 API 不是给 history.pushState 或跨页跳转加动画的,只对单页内**同步 DOM 更新**生效。用错地方,动画就只剩淡入。
关键检查点:
-
document.startViewTransition()必须包裹同步操作,比如container.replaceChildren(newNode);里面塞await fetch()或setTimeout就失效 - 新旧元素都要有完全一致的
style="view-transition-name: title"(大小写、空格、ID 动态拼接都不行) - 旧元素在过渡开始前不能是
display: none、visibility: hidden或opacity: 0;哪怕opacity: 0.001也比彻底隐藏强 - 打开 DevTools → Layers 面板,确认是否生成了
::view-transition-old图层;没有,基本就是 name 没配对或元素不可绘制
最易被忽略的其实是“可绘制状态”——很多动画失效,不是代码写错,而是旧元素在快照前已被设为不可见,浏览器拍不到它。



















