scroll-behavior: smooth 必须写在 html 元素上才可靠生效,仅对原生滚动有效;JS 滚动需显式指定 behavior: 'smooth',且需注意 iOS Safari 兼容性及 WebView 降级处理。

直接用 scroll-behavior: smooth 就能实现,但只对原生滚动生效,且必须加在根滚动容器上(通常是 html 或 body),加错地方就无效。
scroll-behavior 必须写在 html 元素上才可靠
移动端 Safari 和 Chrome 都要求把 scroll-behavior: smooth 声明在 html 选择器里,写在 body 或某个 div 上大概率不触发平滑效果。这是因为页面级滚动的宿主是 html(即使看起来是 body 在动)。
正确写法:
html {
scroll-behavior: smooth;
}
常见错误:
立即学习“前端免费学习笔记(深入)”;
- 只写
body { scroll-behavior: smooth; }→ iOS Safari 完全忽略 - 写在某个
.container上想控制局部滚动 → 局部滚动容器需自己加scroll-behavior,但要确保它有滚动条且是直接滚动宿主 - 用
!important强行覆盖 → 不解决问题,反而掩盖了选择器优先级或继承问题
JavaScript 调用 scrollTo() 时需显式指定 behavior: 'smooth'
启用 scroll-behavior: smooth 后,CSS 控制的锚点跳转(如 <a href="#top">)会自动平滑,但 JS 主动滚动仍需手动声明行为,否则仍是瞬移。
例如回到顶部的按钮:
document.getElementById('back-to-top').addEventListener('click', () => {
window.scrollTo({
top: 0,
behavior: 'smooth' // 必须写,不能省略
});
});
注意点:
-
window.scrollTo()、element.scrollTo()、element.scrollIntoView()都支持behavior: 'smooth',但老版本 Android WebView 可能不支持,需降级处理 - 不要混用
scrollTop = 0和scrollTo—— 前者强制瞬移,会打断平滑动画 - 在快速连续点击“回到顶部”时,多次调用
scrollTo可能产生动画叠加,建议加节流或判断document.scrollingElement.scrollTop === 0
iOS Safari 的兼容细节和隐藏限制
iOS 15.4+ 支持 scroll-behavior: smooth,但存在两个容易被忽略的行为:
- 如果页面有
-webkit-overflow-scrolling: touch(旧式弹性滚动),会禁用scroll-behavior平滑效果,必须移除 - 当
html元素设置了height: 100%或overflow: hidden,可能让根滚动失效,导致scroll-behavior失效 —— 检查document.scrollingElement是否为html,不是的话说明滚动上下文被劫持了 - 部分微信内置浏览器(X5 内核)仍不支持该属性,需 fallback 到 JS 动画(如
requestAnimationFrame逐帧设置scrollTop)
真正起作用的永远是滚动发生的具体元素是否具备 scroll-behavior 且处于激活滚动状态,而不是“加了属性就万事大吉”。尤其在 hybrid App 或 WebView 场景下,滚动容器经常被框架(如 Ionic、Cordova)重定向,这时候查 document.scrollingElement 比查 CSS 更管用。


















