MPA页面过渡需服务端壳页+客户端动态替换content,禁用display动画,用opacity/visibility/transform实现;Safari需will-change+backface-visibility优化。

MPA(多页应用)中加页面过渡动画,本质是“拦截跳转 → 淡出旧页 → 加载新页 → 淡入新页”,不能靠 history.pushState 或单页路由那一套——它天然不适用。浏览器整页刷新时,DOM 一卸载就没了,所有 JS 监听和 CSS 类都会失效。
为什么直接给 body 加 transition 没用
很多人试过在 body 上写 transition: opacity 0.4s,再用 window.location.href = 'page2.html' 跳转,结果动画根本没跑。原因很直接:
-
body元素在跳转瞬间被浏览器强制销毁,transition 连触发机会都没有 -
display: none、visibility: hidden等状态切换在跨页面时无法保持上下文 - 新页面加载后,样式重置,旧页面的动画类名、内联样式全丢失
真正可行的 MPA 过渡方案:服务器端注入 + 客户端钩子
必须让两个页面“共存一小段时间”。主流做法是服务端输出一个统一壳页(shell),把实际内容作为 实操要点: 旧版 Safari(尤其 iOS ≤16)对 注意: 这是最常见也最顽固的坑。有人写: 结果无论怎么切类,动画都不动。因为 正确替代方式只有两个: 所有过渡都必须基于可动画属性,而 MPA 过渡真正的复杂点不在代码量,而在生命周期管理:你得精确控制旧页何时卸载、新页何时可交互、动画中断时如何恢复、以及 SEO 和 history 栈的一致性。这些没法靠一个 CSS 类解决,得靠状态机驱动。 和基础布局。这已接近 SPA,但仍是 MPA 架构(每个 URL 对应真实 HTML 文件)。
,且不带 外层标签(由壳页提供)fetch() 加载目标页面,提取 #content 的 innerHTML,而非整个文档#content 添加 page-exit 类,监听 transitionend 事件后再替换内容opacity: 0; transform: translateY(10px),再加 page-enter-active 类触发过渡void element.offsetWidth 强制重排,否则动画不触发iOS 和 Safari 下动画卡顿的硬解法
transform + opacity 合成优化差,常出现掉帧或首帧延迟。关键补丁只有三个:
will-change: transform, opacity(仅在动画前设置,动画结束立即移除)backface-visibility: hidden,强制开启 GPU 图层filter、box-shadow 或大图背景,它们会破坏合成层will-change 不是“加了就变快”的魔法开关,滥用反而降低性能;它只应在动画开始前 1–2 帧动态添加,例如:element.style.willChange = 'transform, opacity';
setTimeout(() => {
element.classList.add('page-enter-active');
}, 16);
别碰 display: none / block 过渡
.page { transition: all 0.3s; }
.page.hidden { display: none; }
display 属性不可过渡——它没有中间值。浏览器要么渲染,要么彻底剔除,transition 根本无从插手。
opacity + visibility:前者控制透明度,后者控制是否参与渲染流(visibility: hidden 仍占位,display: none 不占位)transform: translateX(100%) 移出视口,配合 pointer-events: none 防止误触display、height(值为 auto 时)、width(同理)都不在此列。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











