核心规则是.tab-panel { display: none; }和.tab-panel:target { display: block; },需确保html中面板有唯一id且href精确匹配#锚点;避免:not(:target),改用visibility+opacity提升可访问性与动画效果。

怎么写基础 CSS 规则让 :target 显示对应面板
核心就两行:.tab-panel { display: none; } 和 .tab-panel:target { display: block; }。前提是 HTML 中每个面板有唯一 id,且链接的 href 带 # 指向它。
别用 :not(:target) 控制隐藏——它容易被其他样式覆盖,而且在动态渲染中会错乱。所有面板统一设隐藏,只给 :target 解除,逻辑更稳。
-
display: none会导致 SEO 和可访问性问题,若需兼顾,改用visibility: hidden; position: absolute; left: -9999px; -
:target优先级和普通类一样,如果前面有.tab-panel { display: block !important; },那:target就不生效 - 移动端 Safari 对 fragment 更新偶有延迟,加
scroll-margin-top: 60px到目标元素上能缓解滚动跳变
为什么点击后内容不显示?三个硬检查点
:target 不是监听器,它只响应浏览器地址栏真实变化,且严格匹配 DOM 中的 id。失效几乎都卡在这三处:
-
href写成javascript:void(0)或被 JSpreventDefault()拦了——必须让默认跳转发生 - 链接是
#Tab2,但元素写的是id="tab2"——大小写、空格、连字符都必须完全一致 - 面板由 React/Vue 异步渲染,初始 HTML 里根本没有
id="tab2"元素——:target匹配发生在 DOM ready 后,没元素就永远不触发
SPA 里 :target 失效怎么办
React/Vue 的 router.push() 或 history.pushState() 默认不触发 :target,因为没真正改变地址栏的 fragment。这不是 CSS 写错了,是链路断了。
- 最轻量解法:
window.location.hash = "#tab2"——它会真实更新 hash、触发:target、自动滚动,兼容性最好 - 若必须用
pushState,得补一句location.replace("#" + id)或调用document.getElementById(id)?.scrollIntoView()(注意:后者只滚动,不触发:target样式) - 别在
useEffect里异步插入带id的面板——组件挂载时就得存在正确id
动画和滚动体验怎么调得自然些
:target 本身不能触发动画,但可以配合 opacity 和 visibility 实现淡入。默认滚动行为也常导致内容被顶部导航栏遮住。
- 禁用
display动画——它是不可过渡属性;改用opacity: 0; visibility: hidden;+:target { opacity: 1; visibility: visible; transition: opacity 0.2s; } -
scroll-margin-top必须写在目标元素上,比如#tab2 { scroll-margin-top: 64px; },而不是.tabs :target——后者多数浏览器不认 - Safari 旧版本对
scroll-margin-top支持不全,上线前务必实测;Safari 15.4 之前还不支持:target在display: contents子元素上生效
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











