scope属性是表格无障碍的底层支撑,必须为<thead>中表头设scope="col"、<tbody>中行标题设scope="row";<caption>须紧贴<table>标签且内容具体;禁用role="search"于<tr>;复杂表格需用id+headers显式关联。
scope 属性不是可选的装饰,而是表格无障碍的底层支撑——没它,屏幕阅读器就只能读“张三、HTML/CSS、22”,不知道哪个是姓名、哪个是年龄。
scope 属性不能省略浏览器和屏幕阅读器靠 scope 区分表头是“管一列”还是“管一行”。没有 scope="col",第一行的 <th>姓名</th> 就只是个加粗文本;没有 scope="row",左侧的 <th>张三</th> 就无法被识别为行标题。结果就是:用户听到“22”,却不知道这数字对应谁、属于哪一栏。
scope="col" 必须用在 <thead> 里横向的表头单元格上scope="row" 必须用在 <tbody> 里每行第一个 <th>(即行标题)<th>,直接用 <td>
<caption> 要写,且必须紧贴 <table> 开始标签<caption> 是屏幕阅读器进入表格时最先读出的内容,相当于“表格说明书”。它不是视觉装饰,而是语义必需项。不写或写错位置(比如塞进 <thead> 里),会导致辅助技术跳过整个上下文。
<table> 标签后、其他任何子元素(<thead>、<tbody>)之前summary 属性替代 <caption>
<tr> 加 role="search"
很多开发者为了“增强语义”,在表格顶部插入一行筛选控件,并给该 <tr> 加上 role="search"。这是严重错误——<tr> 的原生角色就是 row,强行覆盖会破坏整个表格的 ARIA 隐式结构,触发 aria-requires-children 报错。
立即学习“前端免费学习笔记(深入)”;
<tr>,内部用 <th scope="col"> 或 <td> 包裹输入框aria-label(如 aria-label="按姓名筛选"),而不是给整行加 rolearia-labelledby 指向列头 id)headers 关联当表格出现跨行(rowspan)、跨列(colspan)或多层表头时,scope 已经不够用了。此时必须用 id + headers 显式绑定数据单元格和它的所有表头。
<th> 加唯一 id(如 id="name-header")<td> 上用空格分隔多个 id:headers="name-header dept-header"
headers 值真正难的不是写对 scope,而是坚持在每一处 <th> 出现时都问一句:“它管的是行还是列?”——这个习惯比任何工具都管用。