浏览器原生监听radio的checked变化,:checked伪类直接响应真实dom状态,无需js;必须用~选择器因容错性强,能匹配后续所有同级面板;display:none不可过渡,需用opacity/transform等可动画属性。

因为浏览器原生监听 input[type="radio"] 的 checked 属性变化,CSS 通过 :checked 伪类直接响应这个真实状态,无需 JS 注册事件或操作 DOM。
为什么不用 JS 就能“切换”?
浏览器对 input[type="radio"] 的互斥逻辑(同 name 下仅一个可选中)是硬编码在渲染引擎里的。用户点击 label 或控件本身时,checked 属性立即更新,触发 :checked 伪类匹配——整个过程由浏览器同步完成,不经过 JS 引擎。
-
:checked不是“模拟状态”,它只匹配 DOM 中真实存在的checked属性值,比任何 JS 管理的 state 更可信 - 只要结构合法(
input在面板前、同父级、name一致),样式就会自动生效,没有延迟或竞态 - 键盘用户按
Tab切换焦点、空格键选中,同样触发:checked,无障碍支持天然存在
为什么必须用 ~(通用兄弟选择器)?
:checked ~ .panel 能命中所有后续同级 .panel 元素,而 :checked + .panel 只能选中紧邻的下一个。真实 HTML 结构里,label、图标、说明文字常插在 input 和内容块之间,~ 容错性强;+ 一旦中间多一个元素就彻底失效。
-
:checked .panel(后代选择器)无效:.panel 不是input的子元素 -
:checked > .panel(子选择器)无效:同上,DOM 结构不满足父子关系 -
name属性拼错、大小写不一致、漏写,会导致多个 radio 同时checked,所有面板一起显示
为什么不能直接用 display: none 做过渡动画?
display 是离散属性,无法参与 transition。强行加 transition 会完全静默失效,看不出任何动画效果。
- 正确做法是组合
visibility、height、opacity或transform:比如初始设visibility: hidden; height: 0; overflow: hidden;,激活时设visibility: visible; height: auto; opacity: 1; -
height: auto本身不可过渡,所以实际常配合固定高度(如height: 200px)或用max-height(但需预估上限值) - 只对
opacity或transform过渡最稳妥,视觉平滑且性能好
最容易被忽略的三个结构细节
这些错误都不报错,但会让整个 Tab 切换完全不动:
-
input和.panel不在同一个父容器内——~选择器跨不了父级 -
label没写for属性,或for值与input[id]不匹配,导致点击无响应 - 默认项没加
checked(不是checked="true"),而是靠 CSS 强行显示第一个面板——首次加载时无内容可见
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











