复杂表头必须用id+headers显式绑定,禁用scope;多级结构应拆分为多个语义化独立table并配caption;caption须为table首个子元素且不可隐藏。

复杂表头必须用 id + headers,不能只靠 scope
当表头出现跨行(rowspan)、跨列(colspan)或多层嵌套时,scope 属性会失效或被错误推断。屏幕阅读器无法自动关联“Biology → Practical”这种二级标题与下方具体数据单元格,必须显式绑定。
常见错误现象:用户听到“85”,却不知道这是 Biology 的 Practical 还是 Theory 成绩;或者某列数据被重复读出多个表头,顺序混乱。
<th> 必须带唯一 <code>id,比如id="bio-prac"、id="chem-theory"<td> 的 <code>headers值是空格分隔的多个id,顺序即读出顺序(如headers="student bio-prac")- 不要混用
scope和headers——一旦启用headers,scope就被忽略 - 避免给同一
<th> 设置多个 <code>id;每个id只能对应一个语义维度(学科、考核类型、年份等)scope="rowgroup"仅适用于<tbody> 首行,不是万能分组标签 <p><code>scope="rowgroup"不是给任意<th> 加上就能“标记一组行”的快捷方式。它只在 <code><tbody> 内部、且作为该 <code><tbody> 的第一行时才被辅助技术正确识别为“此标题管下面所有 <code><tr>”。放在 <code><thead> 或独立 <code><tr> 里毫无作用。 <p>使用场景非常明确:季度报表、部门分组、服务类别等逻辑连续的数据块,且每组都用独立 <code><tbody> 包裹。<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> <ul><li>必须配合 <code><tbody> 使用,单独写 <code><th scope="rowgroup">Q1</th>在<tr> 里无效 <li> <code>colspan要覆盖整行(如colspan="5"),否则屏幕阅读器可能只读部分单元格 - 不支持嵌套
scope="rowgroup"——比如“Q1 → Jan”这种二级分组,得改用headers或拆表 - 某些旧版 JAWS 版本对
scope="rowgroup"支持不稳定,关键业务建议辅以aria-labelledby - 子表之间用
<h3>或语义化 section 标记分隔,便于 heading 导航 - CSS 可统一控制外观(如边框、间距),不影响 HTML 结构语义
- 响应式断点更易处理——不同子表可按需折叠/展开,而非整张大表重排
多级表头优先拆成多个独立 <table>,而非硬塞进一张表
医疗账单、保险条款、财务附注这类含 3 层以上逻辑分组的表格,强行维持单表结构会导致 headers 维护成本爆炸、易出错,且多数屏幕阅读器导航体验差。WCAG 明确推荐「分表策略」为 AA 级合规首选。
真实兼容性影响:NVDA + Firefox 能准确跳转每个 <caption></caption> 对应的 <table>;VoiceOver 在 iOS 上对单表内多 <code><tbody> 的 <code>scope="rowgroup" 支持有限,但对独立 <table> 的 <code><caption></caption> + <thead> 组合识别稳定。
<ul>
<li>每个子表必须有独立 <code><caption></caption>,例如 <caption>住院费用明细</caption>
<caption> 必须紧贴 <table> 开始,且不可省略
<caption></caption> 是表格的“说明书”,不是装饰。它出现在 DOM 顺序最前,屏幕阅读器启动时第一个读出的就是它。把它丢到 <tbody> 里、或用 CSS 隐藏再用 <code>aria-label 替代,都会破坏可访问性链路。
容易踩的坑:团队常把 <caption></caption> 当作视觉标题,用 display: none 隐藏,以为加个 aria-label 就够了——但 aria-label 会完全覆盖 <caption></caption> 内容,且不被所有 AT 支持。
-
<caption></caption>必须是<table> 的第一个子元素,位置错误将导致 AT 忽略 <li>内容要简洁但具上下文,比如 <code><caption>2024 年华东区销售数据(单位:万元)</caption>,而不是“销售表” - 禁用
summary属性(已废弃),也不要用aria-describedby指向外部段落替代<caption></caption> - 若需补充说明,可在
<caption></caption>后紧跟<p class="visually-hidden">...,用 CSS 隐藏但保留在可访问流中
实际复杂度往往藏在「谁来维护
headers 值」和「是否真能说服产品接受拆表」这两件事上。技术方案清晰,落地阻力却常不在代码里。



















