原生标签默认互斥展开,要允许多项同时展开,须弃用它,改用+aria-expanded+display或max-height控制,每个面板独立切换状态,不联动其他项。

HTML手风琴默认只允许单个展开,怎么改成允许多项同时展开?
原生 <details></details> 标签实现的手风琴是单展开的——点击一个 <details></details>,其他已开的会自动收起。这不是浏览器 bug,而是规范行为。要支持多项同时展开,必须放弃 <details></details> 的默认逻辑,改用 aria-expanded + display 控制显隐。
用 aria-expanded 和 CSS 实现多开手风琴的关键步骤
核心思路:用 <button></button> 触发器控制每个面板的显隐状态,不依赖 <details></details> 自带折叠逻辑。
- 每个手风琴项用
<div class="accordion-item"> 包裹,含 <code><button aria-expanded="false"></button>和对应<div class="accordion-panel"> <li>初始时所有 <code>accordion-panel设为display: none,aria-expanded为"false" - 点击按钮时,仅切换自身
aria-expanded值和对应面板的display,不操作其他项 - 必须手动加
aria-controls(指向面板id)和id配对,否则屏幕阅读器无法关联
<div class="accordion-item"> <button aria-expanded="false" aria-controls="panel-1">标题一</button> <div id="panel-1" class="accordion-panel">内容一</div> </div>
JavaScript 控制多开时容易漏掉的三个细节
只改 display 不够,可访问性和交互反馈必须补全。
- 每次点击后,需同步设置
button.setAttribute('aria-expanded', 'true'/'false'),不能只靠 CSS 类切换 - 键盘操作必须支持:给
button加tabindex="0",监听Enter和Space键触发展开/收起 - 避免重复绑定:如果动态插入新项,不要对整个
document反复addEventListener('click', ...),用事件委托更安全
为什么不用第三方库(如 Bootstrap Accordion)?
Bootstrap 默认也是单开模式,开启多开需额外配置 data-bs-collapse="accordion" 并移除父容器上的 data-bs-parent。但这样会丢失 aria-labelledby 关联,需手动补全语义属性。纯手写反而更可控,尤其当项目已用 Tailwind 或自定义动画时,引入整套 Bootstrap JS 显得冗余。
立即学习“前端免费学习笔记(深入)”;
真正麻烦的是过渡动画与 height 的配合——用 max-height 模拟展开动画比直接切 display 更平滑,但需要预估内容最大高度;而 transform: scaleY() 虽然无需预估,却可能影响子元素内 position: absolute 的定位。这些细节,往往比“允许多开”本身更耗时间调试。



















