html { scroll-behavior: smooth; } 是实现平滑滚动的正确写法,必须作用于 html 元素而非 body;它仅对锚点跳转和 scrollintoview() 等程序化滚动生效,不影响手动滚动;:target 仅响应 url hash 匹配,不控制滚动行为,二者需配合使用。

直接用 html { scroll-behavior: smooth; } 就能实现平滑滚动,:target 本身不控制滚动,只负责样式响应——两者要分开配,否则容易以为“加了 :target 就自动平滑”而漏掉关键一行。
scroll-behavior 必须作用在 html 元素上
scroll-behavior 只对滚动容器生效,而整个视口的滚动容器是 html,不是 body。写在 body 上完全无效。
- ✅ 正确写法:
html { scroll-behavior: smooth; } - ❌ 错误写法:
body { scroll-behavior: smooth; }(无效果) - ⚠️ 注意:该属性不影响用户手动滚动,只作用于锚点跳转、
scrollIntoView()等程序化滚动
:target 样式不生效的三大硬性前提
:target 是纯匹配机制,不带容错。以下任一条件不满足,样式就“隐身”:
- ID 值必须合法:不能以数字开头,
<section id="1section"></section>是非法的,#1section:target永远不触发 - ID 必须全局唯一:重复 ID 会让浏览器无法确定目标,
:target行为不可预测(可能匹配第一个,也可能不匹配) - ID 必须与 URL hash 完全一致:区分大小写,且不能含空格或特殊字符;
#FAQ不会匹配<div id="faq"> <h3>固定导航栏遮挡目标内容?用 <code>scroll-margin-top平滑滚动后,目标元素默认贴顶显示,常被
position: fixed的导航栏盖住。这不是:target的问题,而是定位偏移没调好。- 给目标元素加偏移:
.content-section { scroll-margin-top: 64px; }(数值 ≈ 导航栏高度) - 不要用
padding-top + margin-top负值的老方案:会破坏文档流,影响其他样式和可访问性 -
scroll-margin-top是现代标准解法,兼容 Chrome 69+、Firefox 68+、Safari 15.4+
:target配动画得用@keyframes,别碰transition:target是离散状态切换(有/无),没有中间态,所以transition对它无效。想加入场动效,必须走 CSS 动画。- ✅ 可行:
section:target { animation: highlight 0.4s ease-out; }+@keyframes highlight { ... } - ❌ 无效:
section { transition: background-color 0.3s; } section:target { background-color: #ffeb3b; } - ⚠️ 动画里避免触发布局重排:别对
height、margin、padding做动画,优先用transform和opacity
真正难调的不是写法,而是当页面由框架动态渲染(比如 Vue 的
v-if或 React 的条件渲染)时,:target不会回溯生效——hash 在节点挂载前就存在,它就永远“看不见”。这种场景下,得靠 JS 监听hashchange手动触发样式或滚动。 - 给目标元素加偏移:











