<p>:id 必须与 URL 中 # 后片段严格一致(大小写、符号均需匹配),且唯一;:target 选择器特异性为 class 级(0,1,0),易被覆盖;scroll-margin-top 需直接作用于目标元素而非 :target 规则中。</p>

目标元素必须有 id,且值与 URL 中的 # 后片段严格一致
浏览器只认 id 属性,class、name 或 data-id 都无效。比如 URL 是 #faq-2,就必须存在 <div id="faq-2"></div>。大小写、空格、连字符都要完全匹配——#FAQ-2 和 id="faq-2" 不会触发 :target。
常见错误现象:点击链接没反应,检查开发者工具里该元素是否出现在 :target 的 computed styles 中;若没出现,大概率是 id 缺失或拼写不一致。
- 确保每个
id在页面中唯一(重复 id 会导致行为不可预期) - 避免用 JS 动态渲染后漏掉
id(如 React/Vue 条件渲染未执行,DOM 中实际无该元素) - 不要在 SSR 页面中依赖 :target 首屏高亮——服务端无法感知 hash,样式不会提前生效
:target 样式被覆盖?优先级和选择器结构比想象中关键
:target 的 specificity 等同于一个 class(0,1,0),低于 ID 选择器,也容易被更宽泛的规则压住。比如你写了 h2:target { background: yellow; },但页面已有 article h2 { background: white; },那高亮就看不见。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 用浏览器开发者工具检查 computed styles,看
:target对应的样式是否被 strikethrough - 提升 specificity:改用
#faq-2:target或section h2:target,而不是泛泛的div:target - 慎用
!important——它会让后续维护变困难,尤其在组件化 CSS 场景下 - 临时加
outline: 2px solid red测试是否命中,比背景色更直观(且不受 background 覆盖干扰)
怎么让多个不同 hash 都高亮同一个目标元素?用 ~ 兄弟选择器
原生 :target 只能匹配一个元素,但你可以让多个锚点(如 #sun、#hot、#yellow)都触发对同一个 <h1> 的高亮,前提是它们在 DOM 中位于该 <h1> 之前,且同级。
正确写法:
/* 排除空锚点自身加 outline(影响可访问性) */
:target:not(a) { outline: none; }
<p>/<em> 所有 :target 后面出现的 h1 都高亮 </em>/
:target ~ h1 {
background-color: #fff8e1;
padding: 0.25em 0.5em;
scroll-margin-top: 64px;
}注意:~ 是通用兄弟选择器,不是相邻兄弟 +;目标元素必须在锚点之后、同一父容器内;若目标被包裹在 <section> 里,就得写成 :target ~ section > h1。
滚动定位被 fixed header 挡住?别在 :target 里设 scroll-margin-top
scroll-margin-top 是布局属性,不是伪类样式,不能写在 :target 规则里。它必须直接作用于目标元素本身(即那个带 id 的元素),否则无效。
正确做法:
- 给目标元素加样式:
<h1 id="faq-2" style="scroll-margin-top: 64px;"></h1>,或用 CSS 类统一控制 - 配合全局
html { scroll-behavior: smooth; }实现平滑滚动 - 兼容性注意:Safari 14.1+、Chrome 92+、Firefox 90+ 支持
scroll-margin-top;旧版 Safari 需用 JS 模拟 - 值推荐用
px或rem,避免用%(计算基准不明确)
最常被忽略的一点::target 是纯响应机制,不控制滚动行为,也不触发重绘。想靠它做核心交互状态(比如选项卡激活)风险很高——SPA 中 hash 更新常被路由库拦截,得靠 JS 补位。



















