按钮点击后子菜单不折叠的最常见原因是 aria-expanded 未同步更新,必须显式设置该属性值为 "true" 或 "false",而非依赖 css 类名或 toggleattribute;嵌套时需阻止事件冒泡;键盘操作须支持 enter/space 并设置 tabindex;aria-controls 必须精确关联唯一 id。

按钮点击后子菜单不折叠,aria-expanded 没同步更新
这是最常见的失效原因:按钮状态和菜单可见性脱节。浏览器只认 aria-expanded 值是否为 "true" 或 "false",不会自动监听 display 或 height 变化。
- 每次点击按钮,必须显式设置
button.setAttribute('aria-expanded', 'true')或'false' - 不要依赖 CSS 类名(如
.is-open)来判断状态,JS 里要读写aria-expanded属性本身 - 如果用
toggleAttribute('aria-expanded'),注意它切换的是存在性,不是值 —— 应该用setAttribute明确赋值
子菜单嵌套时,点击内层按钮触发了外层折叠
事件冒泡会让父级 button 也响应点击,导致多层菜单意外收起。
- 在内层按钮的
click事件处理器里加event.stopPropagation() - 避免给父容器(比如
nav或ul)绑定点击监听,只绑定到具体button元素上 - 层级结构建议严格按语义书写:
button控制紧邻的div[role="region"]或ul,不要跨 DOM 层级操作
用 details/summary 实现最简手风琴,但 Safari 不支持 open 属性动画
details 是原生语义化方案,无需 JS 就能折叠,但 CSS 过渡对 open 属性无效 —— Safari 和旧版 Chrome 都不支持 transition: height 或 max-height 在 details 上生效。
- 若需平滑动画,仍得回退到 JS +
aria-expanded+max-height方案 - 用
details时,确保summary是其唯一子元素,否则部分屏幕阅读器会跳过内容 - 可配合
@supports (selector(details:has(*)))做特性检测,但目前兼容性差,不推荐作为主逻辑
键盘操作失效:回车/空格不能展开,Tab 键跳过按钮
手风琴菜单必须支持键盘导航,否则不符合 WCAG 2.1 AA 标准。常见问题是按钮没设 tabindex="0",或没监听 keydown。
- 每个控制按钮必须有
tabindex="0"(除非已是可聚焦元素,如button[type="button"]) - 监听
keydown事件,当event.key === 'Enter'或' '(空格)时触发展开/收起 - 收起时,焦点应保留在按钮上;展开后,若子菜单首项是链接或按钮,可考虑
focus()到它,但非强制
aria-controls 属性 —— 它需要精确指向子菜单的 id,且这个 id 必须全局唯一。漏写、拼错或重复 ID,都会让屏幕阅读器无法建立按钮与菜单的关联。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











