使用 CSS scroll-behavior 实现平滑滚动
点击锚点链接后,页面瞬间跳转到某个区域,这种体验显得很突兀。它会让用户感到迷失方向,打断阅读节奏,使页内导航显得不够精致。解决方案其实只需一个 CSS 属性——无需任何 JavaScript 库。
核心要点
scroll-behavior: smoothCSS 属性可为锚点链接和编程式滚动 API 启用动画式滚动,无需 JavaScript。- 应将其应用于
html元素,而非body,以便该属性正确地传播到视口。 - 浏览器控制的缓动函数和动画时长无法通过 CSS 自定义——当需要精细控制时再考虑 JavaScript。
- 使用
scroll-margin-top防止固定头部遮挡锚点目标。 - 将规则包裹在
prefers-reduced-motion: no-preference媒体查询中,以尊重用户的无障碍偏好。
什么是 scroll-behavior?它如何工作?
scroll-behavior CSS 属性 控制滚动容器在通过编程方式触发滚动时的移动方式——例如锚点链接、哈希导航或 JavaScript 滚动 API(如 window.scrollTo() 或 element.scrollIntoView())。
它接受两个值:
auto— 默认值。瞬时滚动,无动画效果。smooth— 使用浏览器定义的缓动函数和时长以动画方式滚动。
需要特别说明的一点:scroll-behavior 不会影响用户通过鼠标滚轮、触控板或拖动滚动条触发的滚动。它仅作用于锚点触发和编程式滚动。
缓动函数和动画时长完全由浏览器控制。仅靠 CSS 无法自定义它们。如果你需要特定的时长或自定义缓动曲线,则需要基于 JavaScript 的解决方案。
为页面添加 CSS 平滑滚动
将 scroll-behavior: smooth 应用于 html 元素,即可为整个页面启用平滑滚动导航:
html {
scroll-behavior: smooth;
}
使用 html,而非 body。 当设置在根元素上时,该属性会应用于视口。设置在 body 上则不会传播到视口——这是平滑滚动失效时常见的困惑来源。
这一条声明就能自动处理所有锚点链接的滚动。无需 JavaScript,无需依赖。
实际应用场景
目录导航:
<nav>
<a href="#intro">Introduction</a>
<a href="#usage">Usage</a>
<a href="#examples">Examples</a>
</nav>
返回顶部按钮:
<a href="#top">↑ Back to top</a>
要让”返回顶部”链接精准定位到页面最顶部,请确保页面起始位置存在一个 id="top" 的元素,或使用 href="#" 作为后备方案。一旦在 html 上设置了 scroll-behavior: smooth,这两种写法都能立即生效。
使用 scroll-margin-top 处理固定头部
如果布局中包含固定头部,锚点目标会被部分遮挡在头部之下。可以使用 scroll-margin-top 解决这个问题:
:target {
scroll-margin-top: 80px; /* match your header height */
}
为了覆盖更广泛的场景——包括以编程方式滚动到非当前 :target 的元素——可以将该规则直接应用于 section 元素本身:
section[id] {
scroll-margin-top: 80px;
}
这会偏移浏览器导航到目标元素时的着陆位置——无需 JavaScript。
Discover how at OpenReplay.com.
无障碍:尊重 prefers-reduced-motion
有些用户会因动画滚动而出现晕动症或前庭不适。请务必遵循 prefers-reduced-motion 媒体查询:
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}
此模式仅对未在操作系统设置中关闭动效的用户启用平滑滚动。这是构建无障碍滚动体验的推荐做法。
浏览器兼容性
scroll-behavior 已获得所有现代浏览器的全面支持——Chrome 61+、Firefox 36+、Edge 79+、Safari 15.4+ 和 Opera 48+。全球支持率约为 95%,当前项目无需使用 polyfill。
CSS vs. JavaScript:该选哪个?
| 需求 | 最佳方案 |
|---|---|
| 简单的锚点链接滚动 | CSS |
| 自定义时长或缓动曲线 | JavaScript |
| 基于条件或逻辑的滚动 | JavaScript |
对于大多数页内导航场景——文档站点、落地页、作品集——CSS 已经足够且更优。代码更少,无依赖,原生浏览器性能。
快速实施清单
- ☐ 将
scroll-behavior: smooth应用于html,而非body - ☐ 包裹在
prefers-reduced-motion: no-preference中 - ☐ 为含固定头部的布局添加
scroll-margin-top - ☐ 测试锚点链接和键盘导航
- ☐ 在 iOS Safari 上验证行为表现
结语
CSS 平滑滚动是那种实现成本几乎为零、却能立即让页内导航显得更具设计感的改进之一。一条声明、放置得当,无需触及 JavaScript,就能覆盖绝大多数实际使用场景。
常见问题
scroll-behavior 属性必须设置在拥有视口的滚动容器上,也就是 html 元素。当应用于 body 时,该值不会传播到视口级滚动器,因此锚点链接滚动会回退到默认的瞬时跳转。将规则移到 html 上,平滑动画就能按预期工作。
不能。动画时长和缓动曲线完全由浏览器决定,无法通过 CSS 自定义。如果你的设计需要特定速度或自定义缓动函数,需要使用 JavaScript 方案,例如结合 behavior smooth 的 window.scrollTo 配合自定义动画逻辑,或使用一个手动处理时间控制的小型库。
不会。该属性仅作用于编程式和锚点触发的滚动,例如点击哈希链接、调用 scrollIntoView 或调用 window.scrollTo。用户通过鼠标滚轮、触控板手势、拖动滚动条或键盘方向键发起的滚动不会受到影响,仍然使用浏览器原生的滚动行为。
在目标元素上使用 scroll-margin-top 属性,值与头部高度一致。例如,对带 id 的 section 元素设置 scroll-margin-top 为 80px,会偏移滚动着陆位置,使该区域出现在固定头部下方,而不是被遮挡在头部后面。无需 JavaScript 或额外标记。
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.