纯CSS手风琴必须用checkbox而非radio或button,因radio互斥、button无:checked状态;需input紧邻label和content,用:checked+label+.content或:checked~.content控制,配合max-height过渡实现动画。

能实现,但必须用 <input type="checkbox"> 配合 <label> 和相邻兄弟选择器,不能只靠 <details> 或纯 <div>。
为什么必须用 checkbox 而不是 radio 或 button
:checked 只对 <input type="checkbox"> 和 <input type="radio"> 有效,但手风琴通常需要单开单关(非互斥),radio 会强制关闭其他项,不符合交互直觉。而 button 没有 :checked 状态,无法触发伪类。
- 用
checkbox可独立控制每项展开/收起,无需 JS 状态管理 - 必须把
<input>放在每组内容之前(或之后,但需调整选择器),否则无法用~或+选中后续元素 - 隐藏
<input>时别用display: none—— 它会让:checked失效;改用position: absolute; opacity: 0; pointer-events: none;
如何用 ~ 和 + 精确控制展开区域
关键在于 DOM 顺序:每个 <input> 必须紧邻其对应标题和内容,且内容块要能被该 <input> 通过 CSS 选择器捕获。常见结构是:<input> → <label>(作为点击区)→ <div class="content">。
- 用
input:checked + label + .content可以选中「紧接在 label 后面的 content」 - 如果 content 不是紧邻(比如中间有空格文本节点),改用
input:checked ~ .content,但注意它会匹配所有后续同类元素,需加 class 限定范围 - 展开动画要用
max-height+overflow: hidden,别用height: auto—— CSS 无法过渡到 auto - 示例片段:
input:checked ~ .content { max-height: 300px; opacity: 1; },对应初始状态设max-height: 0; opacity: 0; overflow: hidden;
移动端点击区域小、焦点不可见?这些细节决定体验
纯 CSS 手风琴在真实项目里常因可访问性差被拒——尤其 iOS Safari 对 label 绑定 for 的支持不稳定,且默认无 focus 样式。
立即学习“前端免费学习笔记(深入)”;
- 确保每个
<input>有唯一id,对应<label for="xxx">,不要只靠包裹关系(部分旧浏览器不支持) - 给
label加cursor: pointer和user-select: none,避免误选文字 - 为键盘用户添加
input:focus + label样式,例如加 outline 或背景微调 - 动画时间建议 250–300ms,过长显得卡顿,过短不易感知;同时设置
transition: max-height 0.25s ease-in-out, opacity 0.25s ease-in-out
真正难的不是写出第一版,而是处理 max-height 高度不确定时的动画抖动、IE11 下 ~ 选择器兼容性、以及屏幕阅读器对隐藏 input 的播报逻辑 —— 这些没法靠一个 :checked 解决。


















