VoiceOver and Tables with an Empty First Header Cell

The Problem

I noticed some interesting behaviour with VoiceOver 3 when working with data tables whose first cell in the first, or header, row is an empty td element. In these cases, VoiceOver does not correctly associate data cells with their proper column th header cells. Instead, VoiceOver seems to shift the header cells one column to the left, such that it will identify a data cell in the second column of the table as belonging to the third column. That is, it will read the th element from the third column as the header for a data cell in the second column. Obviously, this can lead to some serious confusion for the user. Considering the fact that JAWS 11, NVDA 2010.2beta1, and Window-Eyes 7.2 don't exhibit this behaviour makes me think it's a bug with VoiceOver.

An Easy Solution

Fortunately, this is pretty easy to rectify by using a th element instead of a td element for the empty first cell in the header row. Explicitly adding the thead and tbody elements also seems to solve the problem. Update (22 August 2012): Explicity adding thead and tbody solves the issue regarding column headers, but introduces some problem behaviour with row headers. In this case, after moving the VoiceOver cursor to a row header in the first column, VoiceOver (at least in Mountain Lion) will announce the row header cell below it seemingly as the column header for the current row header cell.

What is the Correct Markup in Any Case?

Examples from the Accessibility Community

Looking around the web, it's quite easy to find examples of both, where either a td or a th element is used for an empty first cell in a header row. In fact, on a good number of pages that specifically address the creation of accessible data tables, the use of td is fairly common. You can find examples of these at 456bereastreet.com, WebAIM.org, jimthatcher.com, and usability.com.au. Each of these sites is well-respected in the web accessibility community for its expertise, so it is reasonable to assume that the use of a td element for an empty first cell in a header row is quite proper, if it doesn't also benefit accessibility in some way that I'm not aware of.

Examples from the W3C

On the other hand, many of the relevant examples provided by the W3C, for instance, in Tables in HTML documents from the HTML 4.01 specification, section 4.9 Tabular data from the HTML5 specification, and HTML Techniques for Web Content Accessibility Guidelines 1.0, suggest the use of a th element for the empty first cell in a table. At the same time, WCAG 2.0 Technique H51: Using table markup to present tabular information does the opposite and suggests the use of an empty td element.

No Absolute Answer

So there's some variation out there, and it's not clear to me if only one or both approaches are officially correct. We do know that under the HTML 4.01 specification on th and td elements, td is for data cells, while th is for header cells, and where a cell acts as both header and data, td is to be used. But what is the status of an empty cell that occurs as the first cell in a row of otherwise header cells? Since it is empty, it is not really acting as a column header, but nor is it providing any data, and it certainly is not both.

If I had to choose, and I'm not suggesting that such a choice is necessary, I'd probably come out in favour of using a th element, the issue with VoiceOver notwithstanding. This is because, even if empty, the cell exists in a row of column headers, and not data cells, so it seems reasonable and consistent to consider the empty cell as simply an empty column header.

In the end, however, I'm not sure it really matters, except now for the fact that, bug or not, VoiceOver 3 has a problem when td is used for an empty first cell in a header row, particularly in very simple data tables.

Navigating Tables with VoiceOver

To navigate tables using VoiceOver, press Control+Option+Command+T to move from table to table down the page. Add the Shift key to the previous sequence to move up the page to the previous table. Once you've reached a table, press Control+Option+Shift+Down Arrow to start interacting with it, at which point pressing Control+Option with the arrow keys can be used to move up, down, left, and right through the table cells. To hear the column header for each cell, move left or right through the row.

The Test Tables

In each of the following seven tables there are three columns. The first contains people's names, but the header cell is empty. The second and third columns are for phone number and city name, and their column headers are simple th elements. The first cell in each of the data rows is also a th element. Otherwise, the tables vary in the markup used for the first cell in the header row, the use of thead and tbody elements, and of the scope, id and headers attributes.

Of the seven variations presented, only two seem to enable VoiceOver 3 to properly associate column headers with the data cells. These are Test Table #3, which uses a th element for the empty header cell, and Test Table #5, which implements the thead and tbody elements. In the remaining versions, VoiceOver will identify the cells in the first column, which contain people's names, as having the header "Phone#". The phone number data cells will be associated with the header "City", and city data cells will have no associated header announced.

Note: The tables were tested with VoiceOver 3 in Safari 5.02. Content for the tables is borrowed from the example at http://www.w3.org/TR/WCAG-TECHS/H63.html.

Test Table #1

  • First cell in header row is an empty td
  • Does not use thead or tbody
  • VoiceOver does not properly associate column headers with data cells
Table #1
Phone# City
Joel Garner 412-212-5421 Pittsburgh
Clive Lloyd 410-306-1420 Baltimore

Test Table #2

  • First cell in header row is a td with a  
  • Does not use thead or tbody
  • VoiceOver does not properly associate column headers with data cells
Table #2
  Phone# City
Joel Garner 412-212-5421 Pittsburgh
Clive Lloyd 410-306-1420 Baltimore

Test Table #3

  • First cell in header row is an empty th
  • Does not use thead or tbody
  • VoiceOver does properly associate column headers with data cells
Table #3
Phone# City
Joel Garner 412-212-5421 Pittsburgh
Clive Lloyd 410-306-1420 Baltimore

Test Table #4

  • First cell in header row is an empty td
  • Uses tbody, but not thead
  • VoiceOver does not properly associate column headers with data cells
Table #4
Phone# City
Joel Garner 412-212-5421 Pittsburgh
Clive Lloyd 410-306-1420 Baltimore

Test Table #5

  • First cell in header row is an empty td
  • Uses thead and tbody
  • VoiceOver does properly associate column headers with data cells

Update (22 August 2012): Note that explicity adding thead and tbody causes issues with row headers in VoiceOver (tested in Mountain Lion with Safari 6.0) where it will sometimes read the row header from the following row as if it were the column header for the current row reader cell. So this is not really a workable solution.

Table #5
Phone# City
Joel Garner 412-212-5421 Pittsburgh
Clive Lloyd 410-306-1420 Baltimore

Test Table #6

  • First cell in header row is an empty td
  • Uses scope="col" on the "Phone#" and "City" column header cells
  • Does not use thead or tbody
  • VoiceOver does not properly associate column headers with data cells
Table #6
Phone# City
Joel Garner 412-212-5421 Pittsburgh
Clive Lloyd 410-306-1420 Baltimore

Test Table #7

  • First cell in header row is an empty td
  • Uses id and headers attributes to associate data cells in the "Phone#" and "City" columns with their respective column header cells
  • Does not use thead or tbody
  • VoiceOver does not properly associate column headers with data cells
Table #7
Phone# City
Joel Garner 412-212-5421 Pittsburgh
Clive Lloyd 410-306-1420 Baltimore

5 Responses to VoiceOver and Tables with an Empty First Header Cell

  1. 1. Darrell Shandrow:

    Has Apple’s accessibility team been approached about this issue, yet? If so, what was their response?

  2. 2. Jason:

    Hi Darrell,

    I haven’t contacted them yet. It’s on my list of things to do :) I’ll post an update shortly with whatever response I get.

    Cheers

  3. 3. Graham Armfield:

    Have noticed in the past that empty table cells can cause problems for screen readers – and not just the cells at the top either. Not being able to ‘land’ on a cell can spoil the user’s self orientation within a table – especially if there are lots of gaps.

    I used to advise developers to place a non-breaking space or a dash in the empty cells. The dashes could be hidden from sighted users by moving the text off to the left with CSS.

    Might that solve your problem?

  4. 4. Jason:

    @Graham,

    Thanks for your comment.

    Agreed, empty cells anywhere in a table can be slightly problematic for screen reader users. In some, but not all cases, reconsidering the table design to reduce or avoid the use of empty cells, especially header cells, can likely mitigate this problem. In some tables, where a data cell is empty because of a lack of data for that particular cell, something like “n/a” may be more appropriate than simply leaving the cell blank. A dash or hyphen, as you suggest, would also probably be better than nothing.

    In the test tables I used above, the use of an empty header cell for the first column is somewhat forced, as it could easily, and in normal circumstances probably should, have the word “Name” as its content.

    Regarding the use of a non-breaking space or a dash where the first header cell is concerned, the use of a non-breaking space in a td doesn’t help VoiceOver, as demonstrated in Test Table #2. Quickly testing with a hyphen instead of a non-breaking space, there is no change in how VoiceOver deals with the table and column headers. The problem really seems to be with simple data tables that use a td instead of a th for the first header cell while also not explicitly specifying thead and tbody.

  5. 5. Jason:

    Just an update on the feedback I got after contacting the Apple Accessibility team about this issue.

    On October 7th, I emailed Apple about VoiceOver’s problem with empty table header cells, and they responded that they would forward the matter to the appropriate people. On October 28th I emailed them back asking if they had considered the issue or made any plans to address it. Here’s what they said:

    We are unable to comment on development decisions or fixes that may be going into future software updates. We have forwarded your email on to the appropriate people for consideration.

    As such, I’m simply assuming, in good faith, that a fix for the problem is something they’re pursuing. I’ve not updated to Mac OS X 10.6.5 yet, so I don’t know if it resolves the issue.

Comments are now closed.