页面跳动本质是滚动位置突变与动画缺失导致的视觉断层,需 scrollBehavior 逻辑与 CSS scroll-behavior: smooth 协同工作:前者控制跳转行为(如返回 {top: 0} 或 savedPosition),后者作用于 html 元素实现平滑滚动,并配合 nextTick、锚点降级及 prefers-reduced-motion 降级保障兼容性。

路由切换时的“页面跳动”,本质是滚动位置突变 + 滚动动画缺失导致的视觉断层。解决它不是单靠 JS 或单靠 CSS,而是让 scrollBehavior 控制逻辑 和 CSS scroll-behavior 控制表现 协同工作。
scrollBehavior 必须返回有效滚动对象
只写函数不返回值,或返回 undefined、null、空对象,都会让浏览器按默认行为处理——通常是保留原位置或随机跳动。
- 每次进新页都回到顶部:
{ top: 0 } - 点击后退/前进时还原位置:优先判断
savedPosition是否存在,存在就直接返回它 - 带锚点跳转(如
/article#section2):解析to.hash,再用{ el: to.hash }定位 - 避开固定头部:Vue Router 4.1+ 支持
offset,例如{ el: '#contact', offset: { top: -72 } }
HTML 元素必须启用 smooth 滚动行为
scroll-behavior: smooth 不作用在 body 上,也不该写在局部 div 里(除非你只希望那个区域平滑)。它必须加在 html 元素上,因为整个视口滚动由 html 承载。
- 全局生效写法:
html { scroll-behavior: smooth; } - 仅设置
body { scroll-behavior: smooth; }无效,body 不是根滚动容器 - 若页面有自定义滚动容器(如 el-scrollbar),需单独对其设置
scroll-behavior: smooth并确保overflow触发滚动
避免 DOM 尚未就绪导致的定位失败
路由刚切换时,目标元素可能还没渲染出来,el: '#xxx' 会找不到,造成滚动失效甚至报错。
立即学习“前端免费学习笔记(深入)”;
- 锚点滚动建议配合
nextTick或router.isReady()确保 DOM 更新完成 - 动态内容页(如文章详情)可加简单防抖:检测到
to.hash后,延迟 50ms 再执行滚动 - 对不存在的锚点做降级处理,例如 fallback 到
{ top: 0 }
兼容性与降级要主动考虑
不是所有用户都用新版浏览器,也不是所有设备都适合动画。
- 加媒体查询关闭动画:
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } } - 旧版 Vue Router(如 v3)不支持
offset,需手动计算偏移:document.querySelector(el)?.offsetTop - 72 - 移动端 Safari 对
scroll-behavior支持较晚(Safari 15.4+),低版本可回退到 JS 滚动动画库



















