屏幕阅读器只报数字不读表头,是因为未设置或错误设置scope属性:scope="col"必须位于内,scope="row"必须位于每行首个中,否则无法建立行列归属关系,导致“张三”“32”“北京”被孤立朗读而非组合为完整语义。

screen reader 读表格时为什么只报数字不读表头
因为没写 scope,或者写了但位置错——scope="col" 只能出现在 <thead> 里,<code>scope="row" 只能出现在 <tbody> 每行第一个 <code><th> 中。漏掉任一,屏幕阅读器就失去行列归属关系,只能孤立读出“张三”“32”“北京”,无法组合成“张三,年龄 32,城市 北京”。<p>常见错误:<br>
- 把 <code><th> 塞进 <code><td> 里(语义崩坏)<br>
- 用 <code><td> 冒充行标题(屏幕阅读器无视)<br>
- 多级表头时只靠视觉对齐,没配 <code>headers 属性
实操建议:
- 每个 <th> 必须带 <code>scope,且值为 "col" 或 "row"
- 行标题不用 scope="row" 的列,直接用 <td>,别硬套 <code><th>
<br>
- 跨行跨列的 <code><th> 一定要加 <code>id,对应 <td> 用 <code>headers 显式绑定
caption 和 summary 到底怎么用才对
caption 是必须项,summary 是废弃项。前者是表格唯一合法标题,后者现代读屏器完全忽略,axe 等检测工具直接报错。
关键约束:
- <caption></caption> 必须紧贴 <table> 开始标签,且是第一个子元素<br>
- 内容要具体,比如 <code><caption>2026年Q1前端班学员考核成绩</caption>,不是“数据表”
- 不要塞进 <thead> 或 <code><tbody> 里,位置错等于没写<p>替代 <code>summary 的做法:
- 用 aria-describedby 指向页面中一段隐藏说明文本
- 或直接在 <caption></caption> 里补充必要上下文,比如“含缺考与缓考标记”
排序按钮和筛选框怎么让键盘用户可用
排序按钮不是“看起来像按钮就行”,它必须能被 Tab 键聚焦、回车触发、且状态可被读出。筛选框同理——不能只放一个 <input type="search"> 就完事。
排序按钮要点:
- 给 <th> 加 <code>tabindex="0"(不是 role="button")
- 初始 aria-sort="none",点击后按 "ascending" → "descending" → "none" 循环更新
- 视觉箭头图标(▲▼)只是辅助,不能替代 aria-sort
筛选框要点:
- 放在 <td> 里,不是 <code><th> 或 <code><tr>
<br>
- 每个都配 <code>aria-label(如 aria-label="按城市筛选"),或用 aria-labelledby 指向对应列头 id
- 支持 Enter 提交,失焦时也应触发筛选(加防抖)
复杂表头下 headers 绑定为什么总失效
因为 headers 只认 ID 字符串,不看 CSS 位置、DOM 顺序或视觉对齐。你把 <td> 拖到屏幕最右边,只要 <code>headers 写对,读屏器照样按指定顺序播报。
典型失效场景:
- 合并单元格用了 colspan 或 rowspan,但没给参与合并的每个 <th> 加唯一 <code>id
- headers 值里 ID 拼错、大小写不一致、多空格或少空格
- 用 class 或其他属性代替 id,而 headers 只接受空格分隔的 ID 列表
正确写法示例:<th id="q1-header" colspan="2">2026年Q1</th><th id="sales-header" scope="col">销售额</th><td headers="q1-header sales-header">120万</td>
真正容易被忽略的是:每次改 DOM 结构(比如动态插入新列),都要同步检查所有 headers 值是否仍匹配当前 id 集合——这不是一次性配置,而是持续维护点。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











