屏幕阅读器无法读取单选按钮切换后的表格Caption问题求助
表格切换Caption后屏幕阅读器无法读取的问题解决
问题场景
为单个表格设置了两个不同的Caption(Caption A和Caption B),通过单选按钮切换显示。默认的Caption A能被屏幕阅读器正常读取,但切换到Caption B后,虽然视觉上正常显示,屏幕阅读器却无法识别它。
原实现代码
JavaScript
$('#myTable').append("<caption class='cA'>Caption A</caption>"); $('#myTable').append("<caption class='cB hide'>Caption B</caption>"); $('input[type=radio]').change(function() { if(this.value == 'captionA') { $('.main-wrapper').find('.cB').addClass('hide'); $('.main-wrapper').find('.cA').removeClass('hide'); } else if(this.value == 'captionB'){ $('.main-wrapper').find('.cA').addClass('hide'); $('.main-wrapper').find('.cB').removeClass('hide'); } });
CSS
.sr-only { position: absolute; top: -30em; } table.sortable td, table.sortable th { padding: 0.125em 0.25em; width: 8em; } table.sortable th { font-weight: bold; border-bottom: thin solid #888; position: relative; } table.sortable th.no-sort { padding-top: 0.35em; } table.sortable th:nth-child(5) { width: 10em; } table.sortable th button { position: absolute; padding: 4px; margin: 1px; font-size: 100%; font-weight: bold; background: transparent; border: none; display: inline; right: 0; left: 0; top: 0; bottom: 0; width: 100%; text-align: left; outline: none; cursor: pointer; } table.sortable th button span { position: absolute; right: 4px; } table.sortable th[aria-sort="descending"] span::after { content: "▼"; color: currentcolor; font-size: 100%; top: 0; } table.sortable th[aria-sort="ascending"] span::after { content: "▲"; color: currentcolor; font-size: 100%; top: 0; } table.show-unsorted-icon th:not([aria-sort]) button span::after { content: "♢"; color: currentcolor; font-size: 100%; position: relative; top: -3px; left: -4px; } table.sortable td.num { text-align: right; } table.sortable tbody tr:nth-child(odd) { background-color: #ddd; } /* Focus and hover styling */ table.sortable th button:focus, table.sortable th button:hover { padding: 2px; border: 2px solid currentcolor; background-color: #E5F4FF; } table.sortable th button:focus span, table.sortable th button:hover span { right: 2px; } table.sortable th:not([aria-sort]) button:focus span::after, table.sortable th:not([aria-sort]) button:hover span::after { content: "▼"; color: currentcolor; font-size: 100%; top: 0; } .hide{display: none;}
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script> <div class="table-wrap main-wrapper"> Sample test <a href="#">tttttt</a> <div role="radiogroup"> <label class="radio-inline"> <input name="test" type="radio" value="captionA" checked="checked">Opt A </label> <label class="radio-inline"> <input name="test" type="radio" value="captionB">opt B </label> </div> <table id="myTable" class="sortable"> <thead> <tr> <th> <button> First Name <span aria-hidden="true"></span> </button> </th> <th aria-sort="ascending"> <button> Last Name <span aria-hidden="true"></span> </button> </th> <th> <button> Company <span aria-hidden="true"></span> </button> </th> <th class="no-sort">Address</th> <th class="num"> <button> Favorite Number <span aria-hidden="true"></span> </button> </th> </tr> </thead> <tbody> <tr> <td>Fred</td> <td>Jackson</td> <td>Canary, Inc.</td> <td>123 Broad St.</td> <td class="num">56</td> </tr> <tr> <td>Sara</td> <td>James</td> <td>Cardinal, Inc.</td> <td>457 First St.</td> <td class="num">7</td> </tr> <tr> <td>Ralph</td> <td>Jefferson</td> <td>Robin, Inc.</td> <td>456 Main St.</td> <td class="num">513</td> </tr> <tr> <td>Nancy</td> <td>Jensen</td> <td>Eagle, Inc.</td> <td>2203 Logan Dr.</td> <td class="num">3.5</td> </tr> </tbody> </table></div>
输出情况
- 首次加载时,屏幕阅读器播报:Caption A Showing 1 to 10 of 10 entries
- 选择第二个选项时,屏幕阅读器播报:table Showing 1 to 10 of 10 entries
问题根源
HTML规范中,一个<table>元素只能有一个<caption>标签。当你同时添加两个caption时,屏幕阅读器只会识别第一个caption元素——即使你给第一个添加display:none隐藏,阅读器会忽略它,但第二个caption因为不是表格的第一个caption节点,也不会被阅读器读取,导致播报时缺少caption文本。
解决方案
方案1:单Caption切换文本内容
只保留一个caption元素,通过单选按钮切换时修改它的文本内容,这是最符合HTML规范的做法。
修改后的JavaScript代码:
// 初始添加单个caption $('#myTable').append("<caption id='tableCaption'>Caption A</caption>"); $('input[type=radio]').change(function() { if(this.value == 'captionA') { $('#tableCaption').text('Caption A'); } else if(this.value == 'captionB'){ $('#tableCaption').text('Caption B'); } });
方案2:使用aria-labelledby关联文本(备选)
如果需要保留两个文本节点,可以将它们放在表格外,用aria-labelledby让表格关联对应的文本,切换时更新关联的ID:
HTML调整
<div class="table-wrap main-wrapper"> <!-- 隐藏的caption文本 --> <span id="captionA" class="sr-only">Caption A</span> <span id="captionB" class="sr-only">Caption B</span> <!-- 其他内容不变 --> <table id="myTable" class="sortable" aria-labelledby="captionA"> <!-- 表格内容 --> </table> </div>
JavaScript修改
$('input[type=radio]').change(function() { if(this.value == 'captionA') { $('#myTable').attr('aria-labelledby', 'captionA'); } else if(this.value == 'captionB'){ $('#myTable').attr('aria-labelledby', 'captionB'); } });
注意:这里的.sr-only类需要调整为视觉隐藏但仍能被屏幕阅读器读取的标准样式:
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; }
验证效果
使用方案1修改后,切换单选按钮时,屏幕阅读器会正确播报对应的Caption文本:
- 选择Opt A:Caption A Showing 1 to 10 of 10 entries
- 选择Opt B:Caption B Showing 1 to 10 of 10 entries
内容的提问来源于stack exchange,提问作者Geek
相关产品推荐
相关产品推荐

