<p>必须添加 html { scroll-behavior: smooth; },否则 window.scrollTo({ top: 0, behavior: 'smooth' }) 等所有平滑滚动将静默退化为瞬移;该 CSS 规则为浏览器滚动引擎激活前提,body 上设置无效,旧版 Safari 需加 -webkit- 前缀,现代主流环境无需;第三方库可能劫持行为,需排查冲突;锚点跳转须 preventDefault() 避免闪跳;移动端键盘弹出可延迟执行;fixed 导航栏遮挡时应动态计算 offsetHeight 补偿。</p>
必须加 html { scroll-behavior: smooth; },否则所有 js 平滑滚动都会静默失效——这不是可选项,是硬性前提。
为什么写了 window.scrollTo({ top: 0, behavior: 'smooth' }) 却没动画
根本原因几乎总是:CSS 没开。现代浏览器(Chrome 61+、Firefox 68+、Edge 79+、Safari 15.4+)的 behavior: 'smooth' 依赖 html 元素上的 scroll-behavior: smooth 才能激活滚动引擎。
-
body { scroll-behavior: smooth; }完全无效,必须作用在html上 - 旧版 Safari(iOS 15.3 及更早)需加
-webkit-scroll-behavior: smooth;,但当前主流环境已无需前缀 - 如果用了
smooth-scroll或其他第三方库,它们可能劫持锚点行为,导致原生 CSS/JS 冲突,优先移除
点击按钮时页面先闪一下再滚动
这是默认锚点跳转没拦住。浏览器看到 href="#top" 或类似链接,会立即执行 URL hash 变更和瞬移,JS 滚动后知后觉。
- 最干净做法:用
<button type="button">,彻底避开锚点语义 - 若必须用链接,事件监听里必须调用
event.preventDefault() - 别在
onclick属性里直接写 JS,容易漏掉preventDefault;改用addEventListener - 移动端键盘弹出时视口重算,可能导致目标偏移,可加
setTimeout(() => { scrollTo(...) }, 100)延迟执行
fixed-top 导航栏遮挡首屏内容
单纯 window.scrollTo({ top: 0, behavior: 'smooth' }) 会让页面顶部卡在导航栏下方,第一行文字被盖住。
- 补偿值不能硬编码(比如
-56),因为不同设备或主题下高度可能变化 - 正确方式是动态读取:
const navbar = document.querySelector('.navbar.fixed-top'); const offset = navbar ? navbar.offsetHeight : 0; - 然后滚动:
window.scrollTo({ top: -offset, behavior: 'smooth' }); - 别用
getComputedStyle(navbar).height,固定定位元素的计算高度常为auto,offsetHeight更可靠
真正容易被忽略的,是那行不起眼的 html { scroll-behavior: smooth; } ——它不报错、不警告,只是让所有 behavior: 'smooth' 静默退化成瞬移。只要这行没生效,后面所有 JS 逻辑都白搭。


















