headers属性需配合真实id才能生效,仅通过document.getelementbyid()查找,不认class、文本或位置;多级表头用空格分隔id,顺序影响读屏播报;优先级高于scope且不跨表;调试需检查accessibility面板及dom可达性。

headers 属性本身不“关联”td和th,它只是让 写了 一个 最容易被忽略的点是:headers 不是写完就自动连上,它依赖 DOM 中单向声明:“我归这几个
管”,前提是每个
都得有真实、大小写一致、不含空格的
id,否则静默失效。
headers 属性必须配
id 才能生效headers="name"却没效果?八成是<th>没设<code>id,或者id值拼错。浏览器只调用document.getElementById()去查,不认class、不认文本、不靠位置推断。
<th class="name">姓名</th> + <td headers="name"> → 完全无效
<li>
<code><th id="Name">姓名</th> + <td headers="name"> → 大小写不一致,匹配失败
<li>
<code><th id="name dept">部门</th> → id含空格,该id被浏览器忽略,等于没写<th id="name">还没挂载,<code><td headers="name">已渲染 → 首次无障碍树无关联,需手动触发重算或延迟绑定
<h3>多级表头必须用空格分隔 <code>id,顺序影响读屏播报
<td>同时归属「地区 + 季度 + 指标」,<code>headers值必须是"region quarter metric"这样的空格分隔字符串。逗号、引号、竖线、JSON格式——全都不认。
headers="region,quarter" → 解析失败,等同于没写headers="region quarter" 和 headers="quarter region" 都能匹配成功,但NVDA/VoiceOver会严格按空格切分后的顺序依次读出<th>文本,再读<code><td>内容
<li>错误顺序如<code>headers="dept name"会导致读成“部门 张三,姓名 张三”,语义错乱;正确应为headers="name dept"
headers 优先级高于
scope,且不能跨 <tbody> 查找
<p>当<code><td>同时有<code>headers和scope,辅助技术会忽略scope,只走headers指向的id列表。但这个查找范围仅限同一<table>内、且在相同逻辑区域(<code><thead>/<code><tbody>/<code><tfoot>)中的<code><th>元素。
<ul><li><code><th id="year" scope="col">在<code><thead>,<code><td headers="year">在<code><tbody> → 合法,可匹配
<li><code><th id="year">在另一个<code><table>里 → 不匹配,headers不跨表
<li><code><th id="year">被<code>display: none隐藏但仍存在于DOM → 会被读出,可能造成重复播报,应移除id或改用aria-label
headers指向<div id="name">或<code><span></span> —— 只认<th>元素
<h3>调试时看 Chrome DevTools 的 Accessibility 面板</h3>
<p>打开 Elements 面板,选中<code><td>,切换到 Accessibility 标签页,检查 “Related headers” 是否列出你预期的<code>id。如果为空,说明至少有一个id未命中:不存在、拼错、大小写不对、不在当前<table>上下文中。
<ul><li>用<code>document.querySelectorAll('td[headers]')批量检查所有带headers的<td>
<li>对每个<code>td执行td.headers.split(' ').map(id => document.getElementById(id)),过滤Boolean后看结果数组是否完整id节点的实时可达性 —— 无论是渲染顺序、条件显示还是 Shadow DOM 封装,都会打断这个链路。











