真正可用的页面过渡需用CSS transition+transform配合JS类名切换,结合history.pushState同步URL、DOM不重载、前进后退正常,并用hidden属性替代display控制显隐,预加载内容并优化动画性能。

直接用 CSS transition + transform 配合 JS 控制类名切换,就能实现真正可用的页面过渡效果;靠 location.href 跳转或刷新页面,永远做不到“无缝”。
用 history.pushState + 类名切换模拟页面跳转
浏览器地址栏要变、前进后退要正常、DOM 不重载——这三件事必须同时满足,否则就不是无缝,只是“看起来像”。pushState 是唯一能干净更新 URL 又不触发刷新的原生方案。
- 每次点击导航链接时,阻止默认行为:
e.preventDefault() - 调用
history.pushState({page: 'about'}, '', '/about')更新地址栏 - 立刻切换当前视图:移除所有
.page-active,给目标<section id="about">加上该类 - 监听
popstate事件,在用户点后退/前进时,读取event.state.page并执行同样切换逻辑 - 别忘了在页面首次加载时,根据
window.location.pathname主动初始化一次显示
display: none 切换会破坏视频/音频/iframe 的状态
很多教程教人用 style.display = 'none' 控制页面显隐,但这是个隐蔽陷阱:隐藏的 <video> 在 Safari 下仍可能缓冲甚至自动播放;<iframe> 里的计时器、WebSocket 连接不会中断;含 <input> 的表单切走再切回,焦点和滚动位置全丢。
- 正确做法是用
hidden属性:el.hidden = true,它会暂停媒体、释放 iframe 资源、重置表单状态 - 若需动画,CSS 中写
[hidden] { opacity: 0; transition: opacity 0.3s; },而非依赖 display - 不要混用
hidden和display,否则行为不可预测
过渡动画卡顿?检查 transform 和 will-change
纯靠 opacity 做淡入淡出,在低端设备上容易掉帧;直接改 left/top 会触发 layout,更卡。真正流畅的动画只该走合成层。
立即学习“前端免费学习笔记(深入)”;
- 位移动画必须用
transform: translateX(100%),别用left - 加
will-change: transform提前告知浏览器该元素将动画(但别滥用,每个页面最多 2–3 个) - 确保容器有
contain: layout paint style,防止动画时重绘整页 - 移动端务必加
touch-action: manipulation,避免 iOS Safari 把滑动手势误判为缩放
从 A 页切到 B 页时,B 页内容还没加载完怎么办?
用户点了“关于”,结果看到半秒白屏或闪烁,这不是动画问题,是资源加载时机没控住。JS 切换类名不能早于 DOM 就绪。
- 提前用
fetch('/about.html')预加载 HTML 片段(非首屏可懒加载) - 拿到响应后,用
DOMParser解析,提取<body>内容并插入对应<section>,而不是等点击时才 fetch - 如果用外部 CSS/JS,确保它们已内联或预加载:
<link rel="preload" as="style" href="about.css"> - 最简兜底:给目标
<section>设min-height: 100vh,避免高度塌陷导致布局跳动
真正的无缝,不在动画多炫,而在 DOM 状态、资源加载、URL 同步、用户交互这四条线全部对齐;少一个,就是“假过渡”。



















