scroll-behavior: smooth 必须写在 html 元素上才生效,写在 body 或 div 上无效;90% 的不生效源于作用对象错误、id 匹配失败、目标未渲染或被固定头部遮挡,需用 scroll-margin-top 补偿并检查 computed 样式。

scroll-behavior: smooth 必须写在 html 上才生效
写了但没平滑滚动?90% 是误加在 body 或某个 div 上。浏览器只把 html 元素当作根滚动上下文,scroll-behavior 在其他地方声明等于白写。打开开发者工具,选中 html 元素,检查 computed 样式里 scroll-behavior 是否为 smooth,且未被 !important 覆盖(Ant Design、Next.js App Router 等常重置为 auto !important,得显式覆盖)。
SPA 中原生锚点被路由拦截,需手动调用 scrollIntoView
Vue Router / React Router 默认会阻止 #section-1 这类 hash 变更的默认行为,导致 scroll-behavior: smooth 和原生跳转全部失效。
- 监听路由变更(如 Vue 的
onBeforeRouteUpdate,React Router 的useLocation+useEffect) - 从 URL hash 中提取目标 ID:
const targetId = location.hash.slice(1) - 确保目标元素已挂载:动态 tab 或懒加载内容中,
document.getElementById(targetId)可能返回null,需配合MutationObserver或框架的nextTick/flushSync - 调用
element.scrollIntoView({ behavior: 'smooth', block: 'start' }),block: 'start'避免被position: sticky表头切掉顶部
固定头部遮挡目标?用 scroll-margin-top,别碰 margin 或 padding
浏览器默认把目标元素上边缘对齐视口顶部,position: fixed 导航栏会直接盖住内容。用负 margin-top 或额外 padding-top 是布局 hack,会破坏表格行高、标题间距和响应式表现。
- 给目标元素加 CSS:
h2[id], tr[id] { scroll-margin-top: 64px; }(数值 = 固定头部高度,含 border/padding) - 该属性只在目标处于可滚动上下文内生效;若目标在 Shadow DOM 或 iframe 中,需单独设置其容器
- IE 不支持,需降级到
scrollIntoView或window.scrollTo手动偏移
id 命名不合法或不唯一,锚点静默失败
原生锚点机制不报错、不警告,错一点就彻底不动——这是最隐蔽的坑。
立即学习“前端免费学习笔记(深入)”;
-
href必须是#section-1形式,不能是section-1、/#section-1或?id=section-1 - ID 不能以数字开头(
id="1-section"在 Safari 15.4 之前查不到),推荐id="section-1" - 不能含空格、中文、括号、句点(
id="联系我们"或id="contact.us"会中断) - 同一页面中
id必须唯一;重复时只滚动到第一个匹配元素,后续点击全部失效 - 动态渲染场景(React/Vue/AJAX)中,点击时目标
tr#row-123若尚未挂载,document.getElementById返回null,滚动即失败



















