:target伪类实现Tab切换需满足三个硬性条件:URL含#id片段、页面存在对应id元素、二者严格大小写一致;否则样式完全不生效。

:target 伪类能实现纯 CSS Tab 切换,但必须满足三个硬性条件:URL 有 #id 片段、页面存在对应 id 的元素、且两者严格大小写一致;缺一不可,否则样式完全不生效。
为什么点击 Tab 后内容没显示?:target 不匹配的典型原因
最常见的是 HTML 结构没对齐。:target 只认 id,不认 class、data-id 或 name。比如链接是 href="#tab2",那目标容器必须是 <div id="tab2">,写成 <code><div class="tab2"> 就失效。
<ul>
<li>URL 中是 <code>#Tab2,但元素 id="tab2" → 大小写不一致,不匹配
id 属性 → 首次跳转找不到目标,滚动失败id(如重复 id="tab1")→ 行为未定义,Chrome 可能选第一个,Firefox 可能忽略<a name="tab1"></a> 锚点 → 现代浏览器已不支持,:target 完全无视如何让非激活 Tab 真隐藏又不影响可访问性?
直接用 display: none 虽然简单,但会从 DOM 流中移除元素,导致屏幕阅读器跳过、SEO 不收录、JS 获取不到 offsetHeight。更稳妥的做法是视觉隐藏:
- 用
visibility: hidden+position: absolute+left: -9999px:保持 DOM 存在、语义完整、尺寸可读 - 或用
opacity: 0+pointer-events: none:适合需要淡入淡出动画的场景 - 避免对
:target元素本身设display: block,除非你全局重置过display,它默认就是块级
:target 配合滚动定位时 scroll-margin-top 为何不起作用?
scroll-margin-top 必须写在 :target 元素自身上,不是父容器或 body。例如:
立即学习“前端免费学习笔记(深入)”;
#tab1:target {
scroll-margin-top: 64px;
}
如果写了 article :target { scroll-margin-top: 64px; },多数浏览器不会生效——因为该属性只对被滚动到的那个具体元素起效。
- 值推荐用
px或rem,别用%(计算基准不明确) - Safari 14.1 以下版本不支持
scroll-margin-top,需降级用 JS 模拟偏移 - 若页面已设
*:target { scroll-margin-top: 0; }(某些 CSS reset 会这么干),必须显式覆盖掉
现代前端框架里 :target 还能用吗?
在 React、Vue 等默认启用 History API 的项目中,:target 基本失效——因为路由 URL 不带 #,比如 /about 而非 /#about。即使强制切到 hash 模式,也有两个现实问题:
- SSR 首屏渲染时,服务端无法感知客户端 hash,
:target样式不会出现在初始 HTML 中,存在 FOUC(闪屏) - 框架内部的
router.push或history.pushState不触发原生hashchange,:target不响应 - 如果你坚持用,所有跳转必须走原生
<a href="#tab1"></a>,不能用框架封装的 Link 组件
真正容易被忽略的是::target 的样式权重和普通选择器一样,没有特殊加成。一旦被 .content #tab1 这类更具体的选择器覆盖,高亮就消失——得靠开发者工具看 computed styles 里是不是被 strikethrough 了。


















