aria-expanded 是 aria 属性,仅声明展开状态而不触发样式或 dom 变化;必须与可见性、键盘操作、css 动画严格同步,否则导致可访问性缺陷。

aria-expanded 是什么,为什么不能只靠它控制手风琴展开
aria-expanded 是一个 ARIA 属性,用于向辅助技术(如屏幕阅读器)声明某个可折叠元素当前是展开还是收起状态。但它本身不触发任何 DOM 变化或样式切换——它只是“说”状态,不“做”状态。
常见错误是只改 aria-expanded 值却忘了同步:
- 切换对应内容区域的
display或height - 触发 CSS 过渡(比如用
max-height动画时,false对应0,true对应具体高度) - 保持键盘可访问性(比如按空格/回车时也要同步更新)
怎么安全地在 true / false 之间切换 aria-expanded
关键不是“设成 true 或 false”,而是和真实可见状态严格同步。推荐在点击事件里统一处理:
button.addEventListener('click', () => {
const isExpanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', String(!isExpanded));
content.style.display = !isExpanded ? 'block' : 'none';
});
注意点:
- 用
getAttribute('aria-expanded') === 'true'判断,不要用布尔转换(!!button.getAttribute(...)会把字符串"false"也转成true) - 如果用
toggleAttribute,得手动指定值:button.toggleAttribute('aria-expanded', !isExpanded),否则它只增删属性,不设false - 初始值必须显式设为
aria-expanded="false",不能留空或省略
用 CSS 配合 aria-expanded 实现视觉反馈
纯靠 JS 切换 aria-expanded 还不够,最好用 CSS 选择器响应状态变化:
[aria-expanded='true'] + .accordion-content {
max-height: 300px;
opacity: 1;
transition: max-height 0.3s ease-out, opacity 0.2s;
}
[aria-expanded='false'] + .accordion-content {
max-height: 0;
opacity: 0;
overflow: hidden;
}
要点:
-
max-height比height更适合动画,因为height: auto无法过渡 - 必须加
overflow: hidden,否则内容会撑开容器 - 不要用
:not([aria-expanded='true']),IE 和旧版 Safari 对这类否定伪类支持差,老老实实写两个规则
键盘操作下容易漏掉的细节
手风琴组件要支持空格键、回车键展开/收起,但很多人只绑了 click:
button.addEventListener('keydown', e => {
if (e.key === ' ' || e.key === 'Enter') {
e.preventDefault();
// 这里执行和 click 相同的切换逻辑
}
});
还要注意:
-
button元素默认支持空格/回车,但如果用了div role="button",就得自己加tabindex="0"和键盘事件 - 切换后,焦点最好保留在按钮上(
e.currentTarget.focus()),避免用户迷失位置 - 如果内容区有表单控件,展开后建议用
setTimeout(() => content.querySelector('input').focus(), 0)自动聚焦第一个可输入项
aria-expanded 的真假切换本身很简单,难的是让这个真假和视觉、键盘、辅助技术全部对齐。漏掉任意一环,对部分用户来说就等于功能缺失。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











