2
votes

I have one table in my web page. It has column headers as well as row headers. In every cell there is a checkbox. It's not possible to provide visual labels to all the check boxes, so I am providing the labels using 'aria-label' property. When I am navigating using the table shortcut keys (Alt+Ctrl+Arrow keys) the screen reader is announcing- row headers, column headers and 'aria-label' text. Eg.'Action 1 checkbox not checked select action 1 for all event column 2', which is redundant.

So if I remove both the table headers, screen reader will announce only 'aria-label' text, which is meaningful and enough to identify the purpose of the checkbox. But as per the WCAG guideline(1.3.1 Info and relationship) table must have header associated with the table data.

So here are my questions:

If I remove the table headers- Will it violate the WCAG compliance?. What is the interaction of the screen reader users with table?, Do they always need headers for navigation?. Will the screen reader users be able to complete the table activity by hearing 'aria-label' text only?.

Please see the code snippet:

<table>
    <tr>
        <th scope="col" width="40%">Events</th>
        <th scope="col" align="left">Action 1</th>
        <th scope="col" align="left">Action 2</th>
        <th scope="col" align="left">Action 3</th>
    </tr>
    <tr>
    <th scope="row">Select All</th>
    <td><input type="checkbox" name="Action11" id="Action11" aria-label="Select action 1 for all event" /></td>
    <td><input type="checkbox" name="Action12" id="Action12" aria-label="Select action 2 for all event" /></td>
    <td><input type="checkbox" name="Action13" id="Action13" aria-label="Select action 3 for all event" /></td>
    </tr>
    <tr>
        <th scope="row">Event 1</th>
        <td><input type="checkbox" name="Action21" id="action21" aria-label="Select action 1 for event 1" /></td>
        <td><input type="checkbox" name="Action22" id="action22" aria-label="Select action 2 for event 1"  /></td>
        <td><input type="checkbox" name="Action23" id="Action23" aria-label="Select action 3 for event 1"  /></td>
    </tr>
    <tr>
        <th scope="row">Event 2</th>
        <td><input type="checkbox" name="Action31" id="action31" aria-label="Select action 1 for event 2" /></td>
        <td><input type="checkbox" name="Action32" id="action32" aria-label="Select action 2 for event 2"  /></td>
        <td><input type="checkbox" name="Action33" id="Action33" aria-label="Select action 3 for event 2"  /></td>
    </tr>
</table>

Thanks in advance!

3

3 Answers

2
votes

Keep the table headers. When navigating as a table (CTRL+ALT+arrows), the typical screen reader behavior is to only announce the header when a new row or column is reached, which is to prevent unnecessary repetition. However some things, such as announcing row and column numbers, can be customized by the user. Using aria-label here slightly begins to mess with those preferences by forcing repetitive speech.

Instead, use aria-labelledby to associate both the row and column headers with each checkbox as follows:

<table>
    <tr>
        <th scope="col" width="40%">Events</th>
        <th id="a1" scope="col" align="left">Action 1</th>
        <th id="a2" scope="col" align="left">Action 2</th>
        <th id="a3" scope="col" align="left">Action 3</th>
    </tr>
    <tr>
    <th id="sa" scope="row">Select All</th>
    <td><input type="checkbox" name="Action11" id="Action11" aria-labelledby="sa a1" /></td>
    <td><input type="checkbox" name="Action12" id="Action12" aria-labelledby="sa a2" /></td>
    <td><input type="checkbox" name="Action13" id="Action13" aria-labelledby="sa a3" /></td>
    </tr>
    <tr>
        <th id="e1" scope="row">Event 1</th>
        <td><input type="checkbox" name="Action21" id="action21" aria-labelledby="e1 a1" /></td>
        <td><input type="checkbox" name="Action22" id="action22" aria-labelledby="e1 a2"  /></td>
        <td><input type="checkbox" name="Action23" id="Action23" aria-labelledby="e1 a3"  /></td>
    </tr>
    <tr>
        <th id="e2" scope="row">Event 2</th>
        <td><input type="checkbox" name="Action31" id="action31" aria-labelledby="e2 a1" /></td>
        <td><input type="checkbox" name="Action32" id="action32" aria-labelledby="e2 a2"  /></td>
        <td><input type="checkbox" name="Action33" id="Action33" aria-labelledby="e2 a3"  /></td>
    </tr>
</table>
0
votes

I agree with Adam. This table appears to be used for layout rather than for displaying structured tabular data.

There's nothing wrong with layout tables, but you should NOT use table heading <th> elements (use <td> instead), and remove all of your aria markup as well to avoid confusing screen-reader users. Use standard HTML form labels instead of the aria-labelledby attribute.

Putting additional data table markup (i.e. table headers, aria markup) would actually cause it to be less accessible, regardless of what any automated testing tools may tell you.

WebAIM has a pretty good explanation of layout tables vs. data tables, if you're interested in learning more about this subject.

http://webaim.org/techniques/tables/data

0
votes

If I remove the table headers- Will it violate the WCAG compliance?

When you can consider that you are not displaying tabular data and use the table tag for layout purpose, WCAG lets you use a table tag for layout tables.. (as long as it can be linearized)

IMHO, what you are showing is a list of events with 3 actions. You may consider that it's not a data table.

In your case, the problem is that I don't see how, by removing table headers and without visual label for the checkboxes, you would help people without a screenreader know the intent of the checkboxes. aria-label is of no use for people not using a screenreader. WCAG require visual instructions.


Edit for clarity:

WCAG focuses mainly on data tables (where headings are required) but does not forbid layout tables (where headings are forbidden). All the question here is to understand if your table is really a data table or a layout table.

For instance, here, you could have used an ul list:

Events
<ul>
  <li>Event 1
    <input type="checkbox" title="Action1" aria-label="Action1" />
    <input type="checkbox" title="Action2" aria-label="Action2" />
    <input type="checkbox" title="Action3" aria-label="Action3" />
  </li>
  <li>Event 2
    <input type="checkbox" title="Action1" aria-label="Action1" />
    <input type="checkbox" title="Action2" aria-label="Action2" />
    <input type="checkbox" title="Action3" aria-label="Action3" />
  </li>
</ul>

And this makes me think that your table is not a data table, and that you use the table tag only for design for vertical alignment.

This is quite conceptual


EDIT 2: This alternative use of ul vs td (which is just to illustrate that you are not really using a data table) does not solve the problem of a visible label (also, curiously, this not a requirement in WCAG).

My opinion is that a visible label next to the checkbox is the best thing. If you can't, you have two options :

  1. relying on javascript to display the title attribute when the field is focused
  2. use small icons next to each checkbox (with correct alternative text which could be used to label the field)