必须用 radio 而不是 checkbox,因其同名互斥机制确保单选;必须共用 name 值;必须用 ~ 通用兄弟选择器而非 +;面板需与 radio 同级且在其后;隐藏需用 visibility: hidden + height: 0 + opacity: 0 组合。

必须用 <input type="radio"> + :checked + ~ 通用兄弟选择器,三者缺一不可;用 checkbox 或 + 或漏写 name,切换会静默失效。
为什么一定要用 radio 而不是 checkbox
选项卡/面板切换本质是互斥单选:同一时间只能有一个激活。浏览器对同名 <input type="radio"> 的 :checked 状态有原生互斥逻辑——点一个,其他自动取消;而 checkbox 没这机制,CSS 无法“反选”,结果就是多个面板同时显示,页面逻辑错乱。
常见错误现象:label 点击后第二个面板展开,但第一个没收起。
- 所有
radio必须共用同一个name值(如name="panel"),大小写、拼写、空格都算不同 - 不能混用
radio和checkbox控制同一组面板 - 若需“关闭全部”功能,得额外加一个无内容的 radio 项并设为默认选中
~ 和 + 该选哪个?
选 ~(通用兄弟选择器)更稳妥。+ 只匹配紧邻的下一个兄弟元素,DOM 中只要在 radio 和目标面板之间插入一个 <label></label> 或说明文字,样式就完全不生效;而 ~ 匹配后面所有同级兄弟,容错强,适合真实项目中常有文案、图标等插入的结构。
错误写法:input:checked .panel(后代选择器)、input:checked > .panel(子选择器)——两者都不生效,因为 .panel 不是 input 的后代或子元素。
- 推荐结构:
<input type="radio" name="panel"><label>...</label><div class="panel">...</div> - 对应选择器:
input[name="panel"]:checked ~ .panel - 若想限定范围,给父容器加 class,比如
.tabs input:checked ~ .panel
隐藏/显示面板不能只靠 display: none
display: none 会让屏幕阅读器跳过内容,也导致 height、opacity 等过渡动画无法平滑触发。真正可用的组合是:
初始状态:visibility: hidden; height: 0; overflow: hidden; opacity: 0;
激活状态:visibility: visible; height: auto; opacity: 1;
-
height: auto本身不支持transition,所以过渡要加在opacity或transform上 - 必须给默认项的
radio显式加checked属性(不是checked="true"),否则首次加载空白 - 所有被控制的
.panel必须和radio在同一父容器内,且位于其后,否则~找不到目标
最容易被忽略的三个细节
这些错误都不报错,但切换完全不动:
-
for属性漏写或与radio的id不匹配,导致点击label无法触发状态变更 -
radio被包在<div class="panel"> 内部,脱离了同级关系,<code>~失效 - 误把
visibility: hidden写成visibility: collapse(后者仅对表格元素有效)











