aria-expanded 和 aria-controls 必须成对使用并确保 ID 关联与状态同步:aria-controls 指向面板唯一 ID,aria-expanded 动态反映按钮展开状态(true/false),且需与面板显隐一致;面板建议添加 role="region"、aria-labelledby 和同步切换的 aria-hidden。

在折叠面板(Accordion)中,aria-expanded 和 aria-controls 需要成对使用,才能让屏幕阅读器正确识别“哪个按钮控制哪块内容”以及“当前是展开还是收起状态”。关键不是单独写对属性,而是确保它们之间存在明确的 ID 关联和状态同步。
aria-controls 指向目标区域的 id
折叠按钮(如 )必须通过 aria-controls 属性,引用其控制的面板容器的唯一 id。这个 id 必须真实存在于 DOM 中,且不能重复。
- ✅ 正确示例:面板内容
- ❌ 常见错误:
aria-controls 值拼错、ID 不存在、多个按钮指向同一个 ID 却没做状态隔离
aria-expanded 实时反映按钮当前状态
aria-expanded 是布尔属性,必须根据面板实际可见状态动态更新:展开时为 "true",收起时为 "false"。它只写在触发按钮上,不写在面板上。
- 初始状态需与面板默认显示一致(例如面板默认隐藏,则按钮初始
aria-expanded="false") - JavaScript 切换面板时,必须同步设置:
button.setAttribute('aria-expanded', 'true');
button.setAttribute('aria-expanded', 'false'); - 不要写成
aria-expanded=""或aria-expanded="undefined"—— 这会被视为无效值,屏幕阅读器可能忽略
面板容器需配合 role 和 aria-hidden(可选但推荐)
被控制的面板区域建议添加 role="region" 并设置 aria-labelledby 指回按钮的 id,增强语义关联。同时,当面板收起时,加上 aria-hidden="true" 可进一步提示内容不可访问(注意:仅当内容完全隐藏且无需键盘聚焦时使用)。
- 示例结构:
-
aria-hidden="true"要随aria-expanded同步切换;若面板用display: none隐藏,aria-hidden可省略(CSS 隐藏已具备可访问性效果),但显式声明更稳妥
避免常见组合陷阱
- 不要只设
aria-expanded而不设aria-controls—— 屏幕阅读器无法知道它控制什么 - 不要让多个按钮共用同一个
aria-controls值却各自维护独立状态 —— 应确保每个按钮有唯一配对的面板 ID - 不要用 class 名或 data 属性代替 ID 关联 ——
aria-controls只认真实存在的 ID 引用 - 避免在非交互元素(如 )上加这些属性 —— 它们应只出现在可聚焦、可操作的控件上










