aria-controls 必须严格指向页面中唯一、已渲染且具有明确 role 和可读性的 dom 元素 id,需与 aria-expanded 或 aria-selected 等状态属性配合使用,不支持多 id,且目标不可用 display: none 隐藏。

aria-controls 必须指向真实存在的 DOM ID
这个属性不是摆设,它要求 aria-controls 的值必须严格匹配目标元素的 id,且该 id 在当前页面中唯一、已渲染、未被移除。常见错误是拼写不一致(比如 aria-controls="panel-1" 但目标是 id="panel1"),或目标元素还没挂载到 DOM 就提前写了属性。
实操建议:
- 先写目标容器,确保有明确
id,再写控制按钮并填入对应值 - 避免用 JS 动态生成 ID 后忘记同步更新
aria-controls值 - 用浏览器开发者工具的“无障碍”面板检查关联是否生效:选中按钮,看“Related elements”里是否列出目标元素
aria-controls 要和 aria-expanded / aria-selected 配合使用
单独写 aria-controls 没有意义——它只建立“谁控制谁”的关系,不表达状态。必须搭配状态属性,让屏幕阅读器知道“当前是否在控制”。
典型组合场景:
- 折叠面板:
<button aria-expanded="false" aria-controls="detail-panel"></button>+<div id="detail-panel"> <li>标签页:<code><button role="tab" aria-selected="true" aria-controls="panel-home"></button>+<div id="panel-home" role="tabpanel"> <li>下拉菜单:<code><button aria-haspopup="listbox" aria-expanded="false" aria-controls="menu-list"></button>+<div id="menu-list" role="listbox"> <p>注意:状态属性(如 <code>aria-expanded)必须用 JavaScript 动态更新,不能只靠初始 HTML。
anything-to-html下载将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
aria-controls 不支持多个目标 ID
规范只允许一个字符串值,不能写成
aria-controls="panel-1 panel-2"或逗号分隔。如果一个按钮要控制多个区域(比如同时展开详情+加载侧边栏),必须改用其他方式:- 用一个父容器包裹多个目标,并给该父容器设
id,然后aria-controls指向它 - 放弃
aria-controls,改用更明确的语义结构(如role="group"+aria-labelledby) - 优先拆分为多个独立控件——多数情况下,单控多区反而降低可访问性
别为了“省代码”强行复用
aria-controls,辅助技术不会解析空格或逗号分隔的列表。目标容器必须有恰当的 role 和可读性保障
aria-controls关联的不只是任意div。目标区域需要明确角色(role)和内容可读性,否则即使 ID 对得上,屏幕阅读器也读不出有效信息。必须检查:
- 折叠面板目标加
role="region"或role="tabpanel",并建议配aria-labelledby指回触发按钮 - 标签页目标加
role="tabpanel",且需tabindex="0"确保键盘可聚焦 - 菜单目标用
role="listbox"或role="menu",内部项要有role="option"或role="menuitem" - 禁用
display: none或visibility: hidden隐藏目标区域——要用aria-hidden="true"配合显隐逻辑
最常被忽略的是:目标没
role,或者用了aria-hidden="true"却忘了在显示时设为false。 - 用一个父容器包裹多个目标,并给该父容器设










