scope属性必须严格按dom位置书写:表头行用scope="col",行首单元格用scope="row";复杂结构须改用headers绑定,禁用scope与headers混用;caption为必选语义起点,summary已废弃。

scope="col"和scope="row"必须按位置硬写,不能靠视觉对齐猜
浏览器和屏幕阅读器不看CSS样式或表格渲染效果,只认scope值和它在DOM中的实际位置。写错就等于把语义关系彻底搞反。
<thead>里第一行的<code><th>——必须用<code>scope="col"(如<th scope="col">姓名</th>)<tbody>中每行第一个<code><th>——必须用<code>scope="row"(如<th scope="row">张三</th>)- 动态生成时别用
i === 0统一加scope="row":要判断当前遍历的是行还是列 - 首列没表头?别硬塞
<th scope="row">,直接用<code><td> <h3>复杂表头(跨行/跨列/多级)下scope完全失效,必须换headers</h3> <p>一旦出现<code>rowspan、colspan,或“学科 → 实践/理论”这种嵌套结构,scope就失去作用。屏幕阅读器无法自动推断一个<td>属于哪几个维度,只能靠显式绑定。 <ul><li>每个<code><th>加唯一<code>id(如<th id="bio-prac">Biology Practical</th>) - 对应数据单元格用
headers空格分隔多个id(如<td headers="student bio-prac">85</td>) - 禁用
scope与headers混用——只要写了headers,scope会被所有浏览器忽略 - 不要给同一个
<th>设多个<code>id;每个id应代表一个独立语义维度(学科、考核类型、年份)scope="rowgroup"不是万能分组标签,用错等于没写
scope="rowgroup"只在特定结构下被正确识别:它必须是<tbody>内部的第一行<code><tr>里的<code><th>,且该<code><tbody>需包裹逻辑连续的数据行。其他任何位置都无效。 <ul><li>写在<code><thead>里?无效 <li>单独放在<code><tr>中不包<code><tbody>?无效 <li>想表达“Q1 → Jan”二级分组?不支持嵌套,得改用<code>headers或拆表 - 旧版JAWS兼容性差,关键业务建议配合
aria-labelledby兜底 - 必须是
<table>的第一个子元素,不能塞进<code><thead>或<code><div> <li>内容要具体,比如<code><caption>2026年Q1前端班学员考核成绩</caption>,而非“数据汇总” - 已废弃的
summary属性请彻底删除,axe等检测工具会直接报错 - 多级分组表格更推荐拆成多个独立
<table>,每个配自己的<code><caption></caption>,WCAG明确列为AA级首选 真正难的不是查文档写对scope,而是在每次敲下<th>时,下意识问一句:“它管的是上面一列,还是左边一行?”这个条件反射比任何自动化工具都管用。</th>
caption是语义起点,不是可选装饰,位置和内容都不能妥协
没有<caption></caption>,屏幕阅读器进入表格时就失去上下文锚点,尤其当页面有多个表格时,用户可能直接跳过整块内容。











