:checked 能替代 js 控制折叠状态,因其通过 checkbox/radio 的选中状态触发伪类,结合兄弟选择器控制后续元素样式;关键要求是折叠内容必须为 input 的同级后续兄弟节点且结构严格符合 html 顺序。

为什么 :checked 能替代 JS 控制折叠状态
因为 <input type="checkbox"> 或 <input type="radio"> 的选中状态会触发 :checked 伪类,而 CSS 可以通过相邻兄弟选择器(+)或通用兄弟选择器(~)影响后续元素的 display、max-height、opacity 等属性——状态切换完全由用户点击输入框驱动,无需 JS 监听事件。
关键前提是:折叠内容必须是该 <input> 的**后续 DOM 兄弟节点**,且结构可控。常见错误是把内容放在 <label></label> 内部或跨父容器,导致选择器失效。
基础 HTML 结构必须满足的三个条件
以下结构缺一不可,否则 :checked 无法联动内容:
-
<input>必须是type="checkbox"(单个面板)或type="radio"(多个互斥面板),且id唯一 -
<label></label>用for属性绑定到该id,点击区域才有效 - 折叠内容(如
<div class="panel-content">)必须紧跟在 <code><input>后面,且在同一父容器内错误示例:
<label><input><div>...</div></label>—— 此时div不是input的兄弟,而是子元素,:checked + div不匹配。max-height过渡动画怎么写才平滑直接对
display: none/block加transition无效,必须用max-height配合固定值或0切换。但注意:不能设max-height: 0→max-height: auto,因为auto无法过渡。实操建议:
- 预估内容最大高度(如
500px),设max-height: 0→max-height: 500px - 为避免文字溢出,给内容区加
overflow: hidden - 过渡时间建议
0.3s,过长显得迟滞,过短像闪现 - 若内容高度差异大,可对每个面板单独设不同
max-height值
示例 CSS 片段:
input[type="checkbox"] + label + .panel-content { max-height: 0; overflow: hidden; transition: max-height 0.3s ease-in-out; } input[type="checkbox"]:checked + label + .panel-content { max-height: 500px; }多面板互斥时 radio 的坑比 checkbox 多
用
type="radio"实现「单选折叠」看似合理,但容易忽略两点:- 所有 radio 必须有相同的
name属性,否则无法互斥 - 初始状态需至少一个 radio 设
checked,否则首次打开无内容可见;若都不 checked,则所有面板默认收起,但用户点击后可能无法收起已开的其他面板(因没有“全不选”逻辑) -
:checked只能控制后续兄弟,不能反向影响前面的面板,所以多个面板之间无自动收起机制——必须靠相同name触发浏览器原生单选行为
更稳妥的做法:用 checkbox + JS 清除其他项(但这就违背了“不使用 JS”的前提),所以纯 CSS 场景下,radio 是唯一可行方案,只是得接受“必须有默认展开项”这个限制。
真正难的不是写出来,是确保 HTML 顺序和层级不出错;一旦结构偏移一像素,
:checked + *就彻底失效。调试时直接检查元素是否被:checked选中,再看兄弟选择器是否命中目标节点。 - 预估内容最大高度(如











