纯CSS手风琴菜单必须用:checked伪类配合checkbox/radio实现,因:hover/:focus无法维持状态,:target会刷新URL且不支持多选,:has()在Safari中不兼容;结构需为input紧邻内容容器,用+或~选择器控制显隐,动画需用max-height/opacity/transform同句声明并避免display:none。

纯 CSS 实现手风琴菜单完全可行,但必须用 :checked 配合 <input type="checkbox"> 或 <input type="radio">,靠表单控件的选中状态驱动展开/收起——别想用 :hover 或 :focus 做多面板切换,它们无法维持状态、不支持点击关闭自身。
为什么必须用 :checked 而不是 :target 或 :has()
:target 依赖 URL 锚点,每次切换都会刷新地址栏,且无法默认收起其他项;:has() 虽然能模拟“兄弟展开”,但目前(截至 2024 年中)在 Safari 中仍不支持,兼容性不可靠。而 :checked 是所有现代浏览器都稳定支持的伪类,且天然具备“单选/多选”语义,适配手风琴的两种常见模式:
- 单面板展开(用
<input type="radio">+ 相同name) - 多面板自由展开(用
<input type="checkbox">)
<input> 必须紧邻内容容器,且用 + 或 ~ 选择器控制
CSS 无法向上选择父元素,所以结构必须是:<input> → <label>(可选)→ <div class="accordion-content">。只有这样,才能用相邻兄弟选择器 input:checked + .accordion-content 或通用兄弟选择器 input:checked ~ .accordion-content 控制显隐:
<input type="checkbox" id="item1">
<label for="item1">标题 1</label>
<div class="accordion-content">内容 1</div>
input#item1:checked ~ .accordion-content {
max-height: 300px;
opacity: 1;
transform: scaleY(1);
}
.accordion-content {
max-height: 0;
opacity: 0;
transform: scaleY(0);
overflow: hidden;
transition: max-height 0.3s ease, opacity 0.2s ease, transform 0.2s ease;
}
注意:不要用 display: none 切换,它无法触发 transition;要用 max-height + overflow: hidden 搭配动画。
立即学习“Java免费学习笔记(深入)”;
动画卡顿、高度不准?关键在 max-height 的取值和过渡时机
设 max-height: 0 → max-height: 500px 是常见做法,但硬编码固定值容易出问题:
- 内容高度超过预设值,会突然截断
- 内容很短,却要动画拉满 500px,显得拖沓
- 字体大小或 padding 变化时,高度计算失效
更稳妥的做法是:用足够大的安全值(如 max-height: 50rem),并确保内容内无 min-height 或 flex 布局干扰高度坍缩。如果必须精确,只能退回到 JS —— 纯 CSS 没法读取 scrollHeight。
真正容易被忽略的是:所有参与过渡的属性(max-height、opacity、transform)必须写在同一句声明里,否则 Safari 可能跳过部分过渡;另外,label 的 for 属性必须和 input 的 id 完全一致,拼错一个字母就点不动。


















