为什么在使用屏幕 reader 浏览 header 时总是读取上方的 header 按钮?
Why when navigating through the header with the screen reader the upper header buttons are always read?
我的问题是我正在尝试使某些 table 更易于访问,但我遇到了一个非常奇怪的问题,我尝试了多种解决方案但无济于事。我从这张截图中得到了这个 table:
如您所见,当我查看每个 header(如 CSLO、开始日期等)时,它会从上方读取 header。因此,每次我使用选项卡或箭头控件关注任何 header 名称时,它也会从上方读取两个按钮。
我试过将按钮分开,使用不同的角色,取出 类 等,但我真的没有指出为什么它总是触发按钮,即使它们没有聚焦。
它的代码是这样的:
<table
class="table table-bordered table-hover component-editable slolisting dataTable ui-sortable"
data-editable-id="slo-list-237"
id="DataTables_Table_0"
style="display: table"
>
<thead>
<tr class="header_action" role="row">
<th rowspan="1" colspan="1">
<div class="btn-group checkall-actions">
<label
class="btn btn-default component-editable-checkall"
onclick="component.editable.select_all_rows(event, this);"
>
<input type="checkbox" />
</label>
</div>
</th>
<th colspan="7" rowspan="1">
<div
class="btn-group unfocus-actions"
style="display: inline-block"
>
<button
class="btn btn-primary"
onclick="creating_init(event, this);"
>
Add CSLO
</button>
<button
class="btn btn-default"
onclick="showModalSyncCSLO('MATH100 - Mathematics for General Education','237');"
>
CSLO Synchronization
</button>
</div>
</th>
</tr>
<tr class="header_title" role="row">
<th
rowspan="2"
style="width: 60px"
class="sorting_disabled component-editable-multi-selector-row"
role="columnheader"
colspan="1"
></th>
<th
rowspan="2"
style="width: 40em"
class="sorting_disabled"
role="columnheader"
colspan="1"
>
CSLO
</th>
<th
rowspan="2"
class="sorting_disabled"
role="columnheader"
colspan="1"
>
Start Date
</th>
<th
rowspan="2"
class="sorting_disabled"
role="columnheader"
colspan="1"
>
End Date
</th>
<th colspan="2" class="slo" rowspan="1">
SLO Performance
</th>
</tr>
<tr class="header_title" role="row">
<th
class="slo sorting_disabled"
role="columnheader"
rowspan="1"
colspan="1"
>
Expected
</th>
<th
class="slo sorting_disabled"
role="columnheader"
rowspan="1"
colspan="1"
>
Fall 2020
</th>
</tr>
</thead>
有趣的是,这只发生在某些屏幕阅读器上,例如 Chrome 上的 NVDA。
导航 table 时,屏幕 reader 将自动读取列和(如果适用)行 header。
当您将两个按钮放置在这些行中时,它们每次都会被读出。这也是因为您将它们全部设置为 <th>
个元素。
您可以将这些按钮移到 table 之外,并将复选框移动到 select 列的下一行(与 CSLO、开始日期等相同的行)。
这将解决问题。
或者您可以使用 <col>
和 <colgroup>
您可能还想研究使用 <col>
和 <colgroup>
元素定义您的列。这有助于屏幕 readers 正确关联 multi-row headers.
有个great article on how to use these from W3C with plenty of examples and here is a great article on MDN about <col>
and <colspan>
.
你可能仍然会看到按钮被宣布(你可以把它们放在 <td>
中,虽然从技术上讲这不是一个好的做法,但它应该停止宣布问题并且不影响可用性....你会在屏幕上测试 reader 虽然我从未尝试过,但可以肯定!)
其他几个小问题
您当前的 table 中不需要 role="row"
和 role="columnheader"
,默认情况下,<tr>
和 <th>
已经具有这些角色,假设您支持IE8+.
您可以删除 rowspan="1"
和 colspan="1"
- 默认情况下,单元格的大小为 1 行 1 列,因此这是不需要的信息(与可访问性无关,它只会使您的标记更容易读)。覆盖跨度时只需添加 rowspan
和 colspan
。
我的问题是我正在尝试使某些 table 更易于访问,但我遇到了一个非常奇怪的问题,我尝试了多种解决方案但无济于事。我从这张截图中得到了这个 table:
如您所见,当我查看每个 header(如 CSLO、开始日期等)时,它会从上方读取 header。因此,每次我使用选项卡或箭头控件关注任何 header 名称时,它也会从上方读取两个按钮。
我试过将按钮分开,使用不同的角色,取出 类 等,但我真的没有指出为什么它总是触发按钮,即使它们没有聚焦。
它的代码是这样的:
<table
class="table table-bordered table-hover component-editable slolisting dataTable ui-sortable"
data-editable-id="slo-list-237"
id="DataTables_Table_0"
style="display: table"
>
<thead>
<tr class="header_action" role="row">
<th rowspan="1" colspan="1">
<div class="btn-group checkall-actions">
<label
class="btn btn-default component-editable-checkall"
onclick="component.editable.select_all_rows(event, this);"
>
<input type="checkbox" />
</label>
</div>
</th>
<th colspan="7" rowspan="1">
<div
class="btn-group unfocus-actions"
style="display: inline-block"
>
<button
class="btn btn-primary"
onclick="creating_init(event, this);"
>
Add CSLO
</button>
<button
class="btn btn-default"
onclick="showModalSyncCSLO('MATH100 - Mathematics for General Education','237');"
>
CSLO Synchronization
</button>
</div>
</th>
</tr>
<tr class="header_title" role="row">
<th
rowspan="2"
style="width: 60px"
class="sorting_disabled component-editable-multi-selector-row"
role="columnheader"
colspan="1"
></th>
<th
rowspan="2"
style="width: 40em"
class="sorting_disabled"
role="columnheader"
colspan="1"
>
CSLO
</th>
<th
rowspan="2"
class="sorting_disabled"
role="columnheader"
colspan="1"
>
Start Date
</th>
<th
rowspan="2"
class="sorting_disabled"
role="columnheader"
colspan="1"
>
End Date
</th>
<th colspan="2" class="slo" rowspan="1">
SLO Performance
</th>
</tr>
<tr class="header_title" role="row">
<th
class="slo sorting_disabled"
role="columnheader"
rowspan="1"
colspan="1"
>
Expected
</th>
<th
class="slo sorting_disabled"
role="columnheader"
rowspan="1"
colspan="1"
>
Fall 2020
</th>
</tr>
</thead>
有趣的是,这只发生在某些屏幕阅读器上,例如 Chrome 上的 NVDA。
导航 table 时,屏幕 reader 将自动读取列和(如果适用)行 header。
当您将两个按钮放置在这些行中时,它们每次都会被读出。这也是因为您将它们全部设置为 <th>
个元素。
您可以将这些按钮移到 table 之外,并将复选框移动到 select 列的下一行(与 CSLO、开始日期等相同的行)。
这将解决问题。
或者您可以使用 <col>
和 <colgroup>
您可能还想研究使用 <col>
和 <colgroup>
元素定义您的列。这有助于屏幕 readers 正确关联 multi-row headers.
有个great article on how to use these from W3C with plenty of examples and here is a great article on MDN about <col>
and <colspan>
.
你可能仍然会看到按钮被宣布(你可以把它们放在 <td>
中,虽然从技术上讲这不是一个好的做法,但它应该停止宣布问题并且不影响可用性....你会在屏幕上测试 reader 虽然我从未尝试过,但可以肯定!)
其他几个小问题
您当前的 table 中不需要 role="row"
和 role="columnheader"
,默认情况下,<tr>
和 <th>
已经具有这些角色,假设您支持IE8+.
您可以删除 rowspan="1"
和 colspan="1"
- 默认情况下,单元格的大小为 1 行 1 列,因此这是不需要的信息(与可访问性无关,它只会使您的标记更容易读)。覆盖跨度时只需添加 rowspan
和 colspan
。