Form Controls without Labels in a Table fixed with ARIA
Sometimes it is necessary to have form controls within tables. And while tables provide their own labeling mechanism, it is important that each and every control still has its dedicated label.
Forms in tables are rather rare, but they can be a necessity. Be sure though you are using tables not simply for layout purposes – the days of layout tables are long gone. Forms in tables only make sense if they are handling data that has a tabular structure itself.
It is important that the table itself is marked up properly using table headers <th>
. This allows navigating the table (and the contained form controls) using desktop screen readers’ table navigation: simply press Ctrl + Alt + Up/Down/Left/Right
when inside a table.
But what about navigation in focus mode (using the Tab
key)?
As we know from Placing non-interactive content between form controls, elements can be associated with a form control by using aria-describedby
. So instead of using real <label>
elements, we could try to associate the table headers with the form controls.
Working Example
Explanation
But like in the very first example, JAWS seems to only announce the column headers. Also, this clearly violates our rule that each and every input needs its dedicated label.
So we can barely call this a real improvement, and we recommend just using plain labels (without any ARIA).
Code
<form>
<table>
<thead>
<tr>
<th>
Delivery provider
</th>
<th id="insurance_header">
Insurance
</th>
<th id="comment_header">
Comment
</th>
</tr>
</thead>
<tbody>
<tr>
<th>
<input id="dhl" name="provider" type="radio" /><label for="dhl">DHL</label>
</th>
<td>
<input aria-describedby="insurance_header" type="checkbox" />
</td>
<td>
<textarea aria-describedby="comment_header"></textarea>
</td>
</tr>
<tr>
<th>
<input id="ups" name="provider" type="radio" /><label for="ups">UPS</label>
</th>
<td>
<input aria-describedby="insurance_header" type="checkbox" />
</td>
<td>
<textarea aria-describedby="comment_header"></textarea>
</td>
</tr>
<tr>
<th>
<input id="post" name="provider" type="radio" /><label for="post">Post</label>
</th>
<td>
<input aria-describedby="insurance_header" type="checkbox" />
</td>
<td>
<textarea aria-describedby="comment_header"></textarea>
</td>
</tr>
</tbody>
</table>
</form>
table {
border-collapse: collapse;
}
td, th {
border: 1px solid;
}
NIL