scroll-behavior: smooth 必须写在 html 元素上而非 body;锚点需用唯一、合规 id(非 name);fixed 导航栏遮挡时用 :target 配合 scroll-margin-top 修复。

直接加 scroll-behavior: smooth 就行,但必须加在 html 元素上,不是 body —— 这是绝大多数人第一次失败的原因。
为什么 scroll-behavior: smooth 不生效?
浏览器默认只认 html 根元素的 scroll-behavior 声明;设在 body 上完全被忽略(即使你用 DevTools 看它“生效”了,实际滚动仍是生硬的)。
常见错误写法:
body { scroll-behavior: smooth; } /* ❌ 无效 */正确写法:
立即学习“前端免费学习笔记(深入)”;
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
html { scroll-behavior: smooth; } /* ✅ 必须这样 */- 该声明对所有原生锚点跳转(
<a href="#section1">)自动生效,无需 JS - 不支持 IE,Edge 18 及更早版本也不支持(如需兼容,得 fallback 到
scrollIntoView({ behavior: 'smooth' })) - 如果页面有自定义滚动容器(比如
overflow: auto的 div),需单独给该容器设scroll-behavior: smooth
锚点目标元素必须有可识别的 id,不能只靠 name
HTML5 已废弃 <a name="xxx"> 写法。现代浏览器只通过 id 匹配锚点:
<a href="#contact">跳到联系</a> <div id="contact"></div>
-
id值必须唯一,且不能以数字开头(如id="1section"在部分旧浏览器中可能失联) - 避免空格、中文、特殊符号;推荐用短横线分隔(
id="faq-list") - 如果目标元素是
<h2 id="about">,跳转后浏览器会把它顶部对齐视口——但若顶部被 fixed 导航栏遮挡,需额外处理(见下一条)
fixed 导航栏导致锚点内容被遮挡怎么办?
这是平滑滚动中最常被忽略的视觉问题:跳转后,id 元素贴着视口顶部,却被 position: fixed 的导航栏盖住。
解决方式不是 JS 计算偏移,而是用 CSS :target 配合滚动填充:
html {
scroll-behavior: smooth;
}
:target {
scroll-margin-top: 60px; /* 假设导航栏高 60px */
}-
scroll-margin-top是标准方案,兼容 Chrome 92+、Firefox 97+、Safari 15.4+ - 值可以是 px、rem、vh,但不能是百分比
- 如果要兼容老浏览器,才考虑用 JS 监听
hashchange后调用element.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' })并手动减去 offsetTop
真正要注意的就三点:样式写在 html 上、锚点用 id 不用 name、固定头用 scroll-margin-top 补齐——其余都是干扰项。

















