aria-controls 仅声明元素间的关联关系,不触发任何行为;需配合 JavaScript 控制显隐、同步 aria-expanded 和 hidden/aria-hidden 状态,并确保 ID 存在且目标有 role="region" 等可访问性属性。

aria-controls 的作用不是“控制”,而是声明关联关系
很多人以为 aria-controls 能让点击元素自动展开/收起目标,其实它只是告诉辅助技术(如屏幕阅读器)“这个按钮和那个区域逻辑相关”。浏览器不会因此触发任何 DOM 操作,也不影响 JavaScript 行为。真正控制显隐,得靠你自己写 click 事件 + classList.toggle() 或修改 hidden 属性。
- 必须用 ID 字符串作为值,且目标元素必须存在且有对应
id - ID 不能含空格或特殊字符(如
my-section-1✅,my section❌) - 一个元素可关联多个目标,用空格分隔:
aria-controls="panel1 panel2" - 目标元素建议加
role="region"或语义化标签(如<section></section>),并设置aria-labelledby或aria-label便于理解上下文
怎么写才不会被屏幕阅读器忽略
仅加 aria-controls 不够,目标元素还得满足可访问性基础条件:可见性状态要通过 aria-hidden 或 hidden 显式表达,而不是只靠 CSS display: none —— 后者对辅助技术不透明。
- 推荐用
hidden属性切换显隐:<div id="dropdown-menu" hidden> → 移除 <code>hidden即可见,且屏幕阅读器会感知变化 - 若必须用 CSS 控制,请同步设置
aria-hidden="true/false",并确保属性值与视觉状态严格一致 - 按钮本身应有
aria-expanded="false",并在 JS 中随状态更新该值(例如展开时设为"true") - 避免把
aria-controls加在<a href="#"></a>上——这类链接无默认交互语义,屏幕阅读器可能跳过;优先用<button></button> - 检查目标元素是否已挂载到 DOM:React/Vue 中,如果目标在
v-if或useState初始为 false,那它根本没渲染,ID 自然不存在 - 动态生成 ID 时(如循环列表),确保
aria-controls值与目标id完全一致(包括大小写、连字符、前缀等) - 不要依赖 JS 框架的“key”或“ref”名来生成 ID —— 它们不等于 HTML
id属性值 - 用浏览器 DevTools 的“Accessibility”面板实时查看
aria-controls是否解析出有效节点(右键 → Inspect → 右侧 Accessibility 标签页)
常见错误:ID 找不到、拼写不一致、动态生成没同步
最常遇到的报错是“aria-controls refers to an element that does not exist”,本质就是 ID 引用失效。这在单页应用(SPA)或模板渲染场景中尤其容易发生。
一个最小可用示例(纯 HTML + 基础 JS)
<button
aria-controls="notification-panel"
aria-expanded="false"
onclick="togglePanel('notification-panel')"
>
查看通知
</button>
<div id="notification-panel" hidden role="region" aria-labelledby="notification-button">
<h2 id="notification-button">新通知(3条)</h2>
<p>你有 3 条未读消息。</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p>
</div>
<script>
function togglePanel(id) {
const panel = document.getElementById(id);
const btn = event.target;
if (panel) {
const isHidden = panel.hasAttribute('hidden');
panel.toggleAttribute('hidden');
btn.setAttribute('aria-expanded', !isHidden);
}
}
</script>
注意这里没用任何框架,但已覆盖 ID 关联、状态同步、角色标注三个关键点。真实项目中,遗漏 aria-expanded 更新或忘记给目标加 role="region",是比写错 ID 更隐蔽的问题。


















