请注意,在这种情况下,“适当地”在语义上是有意义的,并且在屏幕阅读器查看时会给出良好的结果。
假设我有一个问题列表,每个问题都有完全相同的一组答案,格式如下:
.grid {
display: grid;
grid-template-columns: auto repeat(5, 1fr);
max-width: 20em;
}
span {
text-align: center;
}
<div class="grid">
<span></span><span>-2</span><span>-1</span><span>+0</span><span>+1</span><span>+2</span>
<span>Question1</span>
<input type="radio" name="question1" value="-2">
<input type="radio" name="question1" value="-1">
<input type="radio" name="question1" value="0">
<input type="radio" name="question1" value="1">
<input type="radio" name="question1" value="2">
<span>Question2</span>
<input type="radio" name="question2" value="-2">
<input type="radio" name="question2" value="-1">
<input type="radio" name="question2" value="0">
<input type="radio" name="question2" value="1">
<input type="radio" name="question2" value="2">
<span>Question3</span>
<input type="radio" name="question3" value="-2">
<input type="radio" name="question3" value="-1">
<input type="radio" name="question3" value="0">
<input type="radio" name="question3" value="1">
<input type="radio" name="question3" value="2">
</div>
显然,这个标记足以按照我想要的方式显示网格,但它在语义上没有意义或无法被屏幕阅读器访问,因为没有机制将标题行中的标签与相应的单选按钮相关联。第一列中的标签与相应行中的按钮之间也没有任何关联。我知道,
<label>
标签仅适用于单个<input>
,所以这不是正确的方法。我认为可能对每行使用 <fieldset>
(并且将 <legend>
设置为出现在第一列中?)是行的正确方法,但是我应该如何关联“-2”、“-1” 、“+0”、“+1”和“+2”及其相关列中的单选按钮?
您可以做两件事:使用
<table>
和 aria-label/aria-labelledby
<table>
每一行都是一个问题,每一列都是 -2 到 +2 之间的等级,每个单元格中都是您可以对问题给出的可能答案。 这只不过是表格数据的一种形式。因此,它应该位于正确的 HTML 表格中。
顺便说一句,您使用了 CSS 网格进行布局,那么为什么不使用真正的
<table>
来简化它呢?
在理想的世界中,每个
<input>
都应该有它的<label>
。但在这里,尤其是如果你追求真正的<table>
,安排起来并不容易。
使用视觉隐藏文本技术是可行的,但不太实用:
<td>
<label class="visually-hidden" for="question1value0">Question 1, grade 0</label>
<input type="radio" name="question1" value="0" id="question1value0"/>
</td>
<td>
<label class="visually-hidden" for="question1value1">Question 1, grade +1</label>
<input type="radio" name="question1" value="1" id="question1value1"/>
</td>
etc.
如您所见,您必须多次重复“问题1”,以及多次“-1”、“0”、“+1”。 这里 aria-labelledby 属性非常有用,并且使代码变得更加容易。它可能看起来像这样:
<table>
<thead>
<tr>
<th> </th>
<th scope="col" id="minus1">-1</th>
<th scope="col" id="zero">0</th>
<th scope="col" id="plus1">+1</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row" id="question1">Question 1</th>
<td><input type="radio" name="question1" value="-1" aria-labelledby="question1 minus1" /></td>
<td><input type="radio" name="question1" value="0" aria-labelledby="question1 zero" /></td>
<td><input type="radio" name="question1" value="1" aria-labelledby="question1 plus1" /></td>
</tr>
...
</table>
如您所见,每个单选按钮都与两个标签相关联,一个用于行(问题),一个用于列(答案)。
如果你不想制作 HTML 表格,你可以采取其他方法。像这样的东西:
<fieldset>
<legend><h2>Question 1</h2></legend>
<input type="radio" ... />
<label for="...">-1</label>
<input type="radio" ... />
<label for="...">0</label>
<input type="radio" ... />
<label for="...">+1</label>
正如您所看到的,通过该解决方案,您不需要重复“问题1”,但仍然需要重复“-1”、“0”和“+1”。
没有标题,这里
<h2>
。这将帮助那些通过标题导航的人,这是最常见和最有效的导航方法之一。
如果你想采用这个解决方案,我让你调整你的CSS。您当然可以继续使用 CSS 网格,也许可以添加一些额外的
<div>
。
带有 HTML 表格和 aria-labelledby 的版本是我的建议,旨在使您的表单最易于访问。
使用 Tab 导航的用户将依次听到“问题 1,答案 1”、“问题 1、答案 2”、“问题 1、答案 3”、问题 2、答案 1”等。 它看起来有点冗长,但优点是他们总是拥有完整的信息。选择不需要的答案的风险较小,即使它很乏味。
如果整个内容都在 HTML 表中,那么弄清楚存在一系列可能答案始终相同的问题将有很大帮助。 通常不使用选项卡导航的更高级的屏幕阅读器用户(因为有许多更有效的快捷方式)可以在表格内垂直和水平地从一个单元格导航到另一个单元格。他们可以通过浏览第一列更快地查看问题列表,快速执行诸如将所有答案设置为 0 的操作,更好地理解从 -2 到 +2 的分级范围,快速比较他们在两个问题之间给出的答案等。 这使得填写表格的整个过程变得不那么痛苦。
如果没有真正的 HTML 表格,这些高级用户将不得不依次浏览每个问题和每个答案。它更加乏味(只是标题少了一点),而且说有更多机会感到无聊并且不把所有内容都填到最后是没有用的。 这就是为什么我会推荐表格版本,甚至超过字段集+图例+标题版本。
如果没有适当的标签,这里以 aria-labelledby 属性的形式,如果您选择
<table>
,高级用户仍然会弄清楚。
但是,那些仅使用选项卡的人不会得到有关每个单选按钮用途的任何指示。
总之,通过在
<table>
中组织您的内容并提供良好的标签,您可以尽最大努力帮助初学者和高级用户。