aria-expanded必须加在触发按钮上而非面板容器,需用javascript动态更新并与dom可见性严格同步,配合aria-controls指向面板id,且面板须设role="region"或role="tabpanel"。

aria-expanded 必须加在触发按钮上,不是加在面板容器里;它必须和真实 DOM 可见性严格同步,否则屏幕阅读器会读错状态。
aria-expanded 该加在哪个元素上?
只加在触发展开/收起的交互控件上,比如 <button></button> 或带 href 的 <a></a>。不能加在 <div id="panel-1"> 这类被控制的内容区上——加了也无效,辅助技术完全感知不到。
<ul>
<li>
<code>aria-controls 要指向面板的 id,所以按钮本身也得有 id(如 id="toggle-btn"),否则关联断裂
role="region"(或语义更明确的 role="tabpanel"),否则屏幕阅读器不知道这是个独立内容块<div role="button" tabindex="0" aria-expanded="false">——它不响应空格键,焦点管理不可靠;用原生 <code><button type="button"></button> 最稳妥
怎么动态更新 aria-expanded 的值?
不能靠 CSS 类切换“假装”状态变了,必须用 JavaScript 显式调用 setAttribute 更新属性值。顺序也很关键:先改视觉状态(比如 hidden 属性),再设 aria-expanded,否则读屏器可能播报错误。
- 展开时:
btn.setAttribute('aria-expanded', 'true') - 收起时:
btn.setAttribute('aria-expanded', 'false') - 别用
btn.ariaExpanded = true——这不是标准 DOM 属性,IE 和旧 Safari 不支持 - 判断真实状态要用
panel.hasAttribute('hidden')或panel.offsetHeight > 0,而不是只看 class 名
为什么图标没转、动画失效、读屏器读错?
aria-expanded 是给辅助技术看的状态快照,浏览器不会监听它来触发 CSS 重绘或 JS 逻辑。光靠属性值变化,什么都不会自动发生。
- CSS 中写
[aria-expanded="true"] { transform: rotate(90deg); }没用——属性是 JS 动态设置的,CSS 不响应变更 - 正确做法是同步操作:
btn.setAttribute('aria-expanded', 'true')+btn.classList.add('is-expanded'),再用.is-expanded写样式 - 动画过渡失效,常因只设
max-height却没配overflow: hidden和transition;height: auto无法参与 CSS 过渡,得用 JS 测量或改用hidden+opacity组合 - 服务端渲染时,初始 HTML 就得写对
aria-expanded="false"和hidden状态,不能等 JS 加载后再补
最易被忽略的是:状态同步不是“一次设置就完事”,而是每次点击、键盘触发、甚至程序化展开都得检查真实 DOM 可见性、更新属性、同步 class、保障焦点流——漏掉任意一环,可访问性就断了。











