:target伪类能作折叠开关,因其原生响应URL hash变化,自动匹配并样式化对应ID元素;需用href="#id"链接与唯一ID面板配合,以:not(:target)控制隐藏,空锚点收起,transition实现动画。

为什么 :target 伪类能当折叠开关用?
:target 匹配 URL 中 fragment(# 后面的部分)所指向的元素。它本质是浏览器原生的“锚点激活状态”,不是 JS 触发的,也不需要监听事件——只要地址栏 hash 变了,匹配的元素就自动获得该伪类。这恰好满足折叠面板“点击切换显隐”的核心需求:一次点击改变 URL hash,一次 hash 变化驱动样式响应。
基础 HTML 结构怎么搭才不踩坑?
关键在两点:锚点链接必须带 href="#id",被控制的面板必须有对应 id;且面板默认要隐藏,只在被 :target 匹配时显示。常见错误是把 display: none 直接写在面板上,导致首次加载时无法看到内容(因为没 hash)。正确做法是用 :not(:target) 或初始状态显式控制:
- 每个折叠项用
<div id="panel-1">...</div>,对应链接为<a href="#panel-1">展开</a> - 面板默认设
display: block,再用#panel-1:not(:target) { display: none; }实现“非目标时隐藏” - 避免给多个面板共用同一
id,否则:target会同时匹配所有——浏览器只认第一个
如何支持“点击收起”和多面板互斥?
:target 本身不提供“取消 target”的能力,所以纯 CSS 无法真正实现“再点一次收起”。但可以绕过:用一个空锚点(如 <a href="#">收起</a>)清空 hash,让当前面板失去 :target 状态。互斥则靠结构约束——每次只允许一个面板被 target,只需确保所有链接都指向各自唯一 id 即可,无需额外逻辑。
示例收起链接:<a href="#">收起</a>,配合 #panel-1:target { display: block; } #panel-1:not(:target) { display: none; },点击它会跳转到页面顶部且清空 hash,自然触发收起。
立即学习“前端免费学习笔记(深入)”;
动画、过渡和兼容性要注意什么?
:target 切换是即时的,要加展开/收起动画得靠 transition 配合高度或 opacity。但注意:height: auto 无法过渡,必须用固定高度、max-height 或 opacity + transform 替代。IE9+ 支持 :target,但 iOS Safari 早期版本对 fragment 变化监听有延迟,建议加 scroll-behavior: smooth 提升体验。
推荐过渡写法:#panel-1 { opacity: 0; transform: scaleY(0); transition: opacity 0.2s, transform 0.2s; } #panel-1:target { opacity: 1; transform: scaleY(1); },比 height 更可靠。
真实项目里,hash 变化会留下浏览器历史记录,用户点返回键会切回上一个面板——这点常被忽略,但恰恰是纯 CSS 方案的天然行为,不是 bug。


















