aria-expanded 必须写在触发按钮上,仅起语义告知作用,需配合 JS 同步切换子列表的 aria-hidden 属性;错误位置包括 li 或 ul;值只能为字符串 "true"/"false",须显式声明初始状态,且与 aria-hidden 严格同步。

aria-expanded 必须写在触发按钮上,不是
<button aria-expanded="false" aria-controls="sub-1">文档</button>- 子列表用
<ul id="sub-1" aria-hidden="true">,收起时加aria-hidden="true",展开时移除 - 不要用
display: none隐藏子列表——它会从可访问性树中彻底删除节点 - ✅ 正确:
button.setAttribute('aria-expanded', 'true') - ✅ 正确:
button.setAttribute('aria-expanded', 'false') - ❌ 错误:
button.ariaExpanded = true(部分浏览器不识别) - ❌ 错误:
button.setAttribute('aria-expanded', '')或null或0 - 子列表 DOM 必须始终存在,初始不可用
display: none或hidden属性隐藏 - JS 初始化时,先读取当前
aria-expanded值,再决定是否显示子列表,避免状态错位 - 懒加载节点要提前占位:空
<ul id="sub-x"></ul>+aria-hidden="true",加载完再替换内容 - 收起时:
button.setAttribute('aria-expanded', 'false')+subList.setAttribute('aria-hidden', 'true') - 展开时:
button.setAttribute('aria-expanded', 'true')+subList.removeAttribute('aria-hidden') - 禁止对子列表用
visibility: hidden或opacity: 0——它们不阻断键盘焦点流
它只起语义告知作用,不控制显隐——你得自己用 JS 切换子列表的 aria-hidden 或 hidden 属性,再同步更新这个值。常见错误是把它加在 <li role="treeitem"> 上,或者直接塞进 <ul> 里,这会让屏幕阅读器忽略状态变化。
正确位置只有一个:节点内那个可点击的 <button>(或带 role="button" 的元素),且该按钮必须有 aria-controls 指向对应子列表 ID。
值只能是字符串 "true" 或 "false",不能是布尔值
写 el.setAttribute('aria-expanded', false) 看似合理,但实际传的是布尔 false,浏览器会自动转成字符串 "false",虽结果对,但逻辑易混淆;更危险的是 el.removeAttribute('aria-expanded'),这会让属性消失,等价于未定义,屏幕阅读器会当作“状态未知”处理,不是 false。
判断状态也必须用字符串比较:el.getAttribute('aria-expanded') === 'true',不能用 !!el.getAttribute('aria-expanded')。
立即学习“前端免费学习笔记(深入)”;
初始状态必须显式声明,不能靠默认
HTML 加载时,如果按钮没写 aria-expanded,辅助技术不会默认它是 false,而是跳过状态读取。哪怕子列表一开始就是收起的,你也得在 HTML 里写明 aria-expanded="false"。
同理,如果某节点默认展开,就写 aria-expanded="true",并确保对应子列表没有 aria-hidden="true"(或已移除)。
配合 aria-hidden 控制子列表显隐,别碰 display 或 visibility
展开/折叠动作发生后,要同时操作两处:aria-expanded 在按钮上,aria-hidden 在子 <ul> 上。这两个值必须严格一致——按钮说“已展开”,子列表就不能有 aria-hidden="true"。
旧版 TalkBack(12 以下)根本不响应动态注入的 aria-expanded,只认初始 DOM 里的静态值;但它能读 aria-hidden 的实时变化,所以这是保底可用的关键链路。
aria-expanded 不是开关,而是“说明书”的一行字;真正干活的是你写的那几行 JS,而且必须在 DOM 变更后立刻执行,不能等 CSS 动画结束,也不能靠 class 切换间接触发。



















