在HTML表格中添加筛选行是提升数据操作效率的常用设计,但要让所有用户都能顺利使用筛选功能,需要正确配置ARIA属性和语义角色,避免辅助技术无法识别筛选行的交互逻辑。
筛选行的语义角色选择
筛选行通常位于表头行之后,由多个包含输入框或下拉选择器的单元格组成。从语义上来说,筛选行不属于表头内容,也不属于表格数据主体,因此不建议使用th标签作为筛选行的单元格标签,也不建议将其放入tbody中。
正确的做法是将筛选行放在thead内部,使用tr标签定义行,单元格使用td标签,同时为整行设置role="row",每个筛选单元格设置role="cell",如果需要明确标识这是筛选区域,可以为筛选行的容器添加role="search"或者通过ARIA属性标注用途。
核心ARIA属性配置
筛选行的核心作用是控制表格数据的过滤,因此需要让辅助技术用户明确每个筛选控件对应的列,以及筛选控件的功能。常用的ARIA属性包括:
aria-label:为没有可见文本标签的筛选控件添加描述,说明该控件对应哪一列的筛选功能aria-controls:指向被筛选的表格主体元素,说明该筛选控件控制的是哪个表格的内容aria-autocomplete:如果筛选输入框支持自动补全,可设置该属性说明补全的方式aria-live:如果筛选结果会实时更新,可在表格主体设置该属性,让辅助技术及时播报更新内容
完整代码示例
以下是一个包含筛选行的表格完整实现,所有ARIA属性和语义角色都已正确配置:
<table id="data-table" border="1">
<thead>
<tr role="row">
<th role="columnheader" scope="col">姓名</th>
<th role="columnheader" scope="col">年龄</th>
<th role="columnheader" scope="col">部门</th>
</tr>
<tr role="row" aria-label="表格筛选行">
<td role="cell">
<input type="text" aria-label="筛选姓名列" aria-controls="data-table-body" placeholder="输入姓名筛选">
</td>
<td role="cell">
<input type="number" aria-label="筛选年龄列" aria-controls="data-table-body" placeholder="输入年龄筛选">
</td>
<td role="cell">
<select aria-label="筛选部门列" aria-controls="data-table-body">
<option value="">全部部门</option>
<option value="技术部">技术部</option>
<option value="产品部">产品部</option>
</select>
</td>
</tr>
</thead>
<tbody id="data-table-body" aria-live="polite">
<tr role="row">
<td role="cell">张三</td>
<td role="cell">25</td>
<td role="cell">技术部</td>
</tr>
<tr role="row">
<td role="cell">李四</td>
<td role="cell">28</td>
<td role="cell">产品部</td>
</tr>
</tbody>
</table>
<script>
// 筛选逻辑示例
const nameInput = document.querySelector('input[aria-label="筛选姓名列"]');
const ageInput = document.querySelector('input[aria-label="筛选年龄列"]');
const deptSelect = document.querySelector('select[aria-label="筛选部门列"]');
const tableBody = document.getElementById('data-table-body');
const rows = Array.from(tableBody.querySelectorAll('tr'));
function filterTable() {
const nameVal = nameInput.value.toLowerCase();
const ageVal = ageInput.value;
const deptVal = deptSelect.value;
rows.forEach(row => {
const cells = Array.from(row.querySelectorAll('td'));
const name = cells[0].textContent.toLowerCase();
const age = cells[1].textContent;
const dept = cells[2].textContent;
const matchName = name.includes(nameVal);
const matchAge = ageVal ? age === ageVal : true;
const matchDept = deptVal ? dept === deptVal : true;
row.style.display = (matchName && matchAge && matchDept) ? '' : 'none';
});
}
nameInput.addEventListener('input', filterTable);
ageInput.addEventListener('input', filterTable);
deptSelect.addEventListener('change', filterTable);
</script>
常见配置错误规避
在设置筛选行的ARIA属性时,需要避免以下常见错误:
- 不要将筛选行的
td标签误用为th标签,筛选单元格不属于列标题,使用th会导致辅助技术误将其识别为表头 - 不要省略
aria-controls属性,该属性能让辅助技术用户明确筛选控件的作用范围,避免混淆多个表格的场景 - 不要在筛选行使用
role="rowheader",该角色仅适用于行标题单元格,和筛选功能无关 - 如果筛选控件有可见的配套文本标签,不需要重复设置
aria-label,避免辅助技术重复播报内容
验证方法
配置完成后,可以使用无障碍检测工具验证配置是否正确,也可以通过屏幕阅读器实际测试:启动屏幕阅读器后,聚焦到筛选输入框,确认能正确播报对应的列名称和筛选功能,修改筛选条件后,确认表格主体的更新能被及时感知。