headers属性需手动精确匹配th的id,大小写、空格、顺序均敏感,动态渲染时须确保th先挂载,多级表头应逐级声明而非并列拼接,且headers优先级高于scope。

headers 属性在多级复杂表头中不是“自动推导”归属关系,而是靠你手动写对 id 字符串、确保它们真实存在且大小写一致——写错一个,屏幕阅读器就只读出部分上下文,甚至完全跳过。
必须给每个参与关联的 <th> 显式设 id
headers 只认 id,不看 class、文本内容、位置或 colspan/rowspan。哪怕视觉上某个 <th> 明显“管着”下面一整块,没 id 就等于不存在。
-
<th>2024年</th>配<td headers="year">→ 无效,缺id -
<th id="Year">2024年</th>配<td headers="year">→ 大小写不一致,匹配失败 -
<th id="q1 sales">Q1 销售额</th>→id含空格,浏览器直接忽略该id,后续所有headers="q1 sales"全失效 - 动态渲染时,
<th id="region">还没挂载,<td headers="region">已输出 → 首次无障碍树无关联,需用 JS 延迟绑定或重置
多级表头用空格分隔多个 id,逗号引号全无效
一个 <td> 同时属于「年份 + 季度 + 地区」,headers 值必须是 "year q1 beijing"。浏览器只把空格当分隔符,其他写法一律解析失败。
-
headers="year,q1,beijing"→ 当作一个 ID 查找,找不到 -
headers=""year" "q1" "beijing"→ 引号成为 ID 字符一部分,查不到目标 -
headers="year q1"漏了beijing→ 屏幕阅读器只读出前两个维度,语义不完整 - 顺序影响播报:NVDA 和 VoiceOver 严格按空格切分后的顺序依次读出每个
<th>文本,headers="region quarter"和headers="quarter region"效果不同
父子表头别在 <td> 层重复写父级 id
多层嵌套的本质是语义链,不是并列拼接。比如「季度」下有「Q1/Q2」,正确做法是逐级声明,而不是让数据单元格直接引用全部层级。
立即学习“前端免费学习笔记(深入)”;
- 顶层:
<th id="quarter">季度</th> - 中间层:
<th id="q1" headers="quarter">Q1</th>(显式声明它属于“季度”) - 数据层:
<td headers="q1">120</td>(只关联q1,语义链自动成立) - 错误写法:
<td headers="quarter q1">→ 读屏器会重复读“季度 Q1 120, Q1 Q1 120”,造成冗余和混淆
headers 和 scope 别混用,前者完全覆盖后者
WAI-ARIA 规范明确:只要 <td> 上有 headers,scope 就被彻底忽略。这不是兼容性补丁,而是硬性优先级规则。
- 简单二维表(无合并、无嵌套)→ 用
scope="col"或scope="row"足够,更轻量 - 出现
rowspan/colspan、嵌套<thead>、跨<tbody>分组 → 必须统一用headers,删掉所有scope - 调试时打开 Chrome DevTools 的 Accessibility 面板,检查 “Related headers” 是否列出全部预期
id;重复id或缺失id会导致整个绑定静默失效
真正容易被跳过的细节是:headers 不是“写完就生效”,它依赖完整的 DOM 结构——<th id="xxx"> 必须在 <td headers="xxx"> 渲染前已挂载,否则首次无障碍树构建就漏掉了。动态场景下这点常被忽略,导致上线后读屏体验断层。



















