Better Connected, Better Results: Table Headers

One of the most common accessibility problems we find when conducting the Better Connected survey is the lack of marked up headers in data tables. So let’s look at why these are important, and how to make sure that tables can be clearly understood.

The importance of table headers

Data tables are a grid of pieces of information, few, (or none), of which are understandable in isolation. They’re displayed in a grid of columns and rows so that it’s easy to refer to the other pieces needed to make sense of the data.

Visually we do this by scanning the rows and columns to identify which holds the information we want, then we skip to the cell that contains the data. If we need reassurance that we’re in the right cell, a quick glance up and left will do the trick. We’ll initially recognise the key (header) cells by position, by a difference of text style or by making an instant decision about the importance or relevance of the data in potential key cells.

At the same time, our minds filter out the unwanted data in the cells between our “target” data and the key data. The combined data from the key and data cells should then make sense. It’s all done in the twinkling of an eye, and often we aren’t even conscious that we’re doing it, unless the table is huge and the cross-referencing requires effort.

Now, you probably knew all that anyway, but I’ve described the full process to underline the kind of things that we might take for granted:

  • Locating potential key cells.
  • Determining their importance at a glance.
  • Skipping past or ignoring intervening data.

People who can’t see, obviously can’t do any of the above. Their screen readers may be able to do some of it, but they need markup to recognise the difference between data and key cells as the assumption that the top row and left-hand columns hold key information, isn’t safe.

Let’s look at an inaccessible example, (with no marked up headers):

Inaccessible example: 1. European pet ownership made up statistics

Imagine that you’re interested in how many people in France own cats, the data is in Column 6 of Row 4.

Rank Country Population (millions) Pet owners (millions) Pet ownership Cat owners (millions) Cat ownership
1 UK 60.36 21.8 36% 10.2 17%
2 Greece 11.33 3.9 34% 2.2 19%
3 France 61.36 20.3 33% 7.9 13%

This doesn’t seem too challenging, but screen readers don’t slide over data as easily as eyes do, they focus on, and announce, one cell at a time. Look at the steps that a JAWS user would need to perform, once the focus entered the table, to get the information that there were 7.9 million cat owners in France.

  1. Navigate across the top row to the Cat owners cell (5 depressions of the down arrow key), taking note en route that the Country data is in the second column.
  2. Navigate down the cat owners column (holding down CTRL and Alt, then depressing the down arrow key).
  3. Cross fingers that the headers have been marked up, as the Country info isn’t in the left hand column, so JAWS can’t be set to read top and left -most cells as titles. Query JAWS for the table titles (hold down Ctrl and Alt, then depress 5 on the number pad (right of the keyboard)).
  4. Hear "Cat owners (millions), 1, 10.2", because headers haven’t been coded.
  5. Navigate back to second column: (press up arrow 4 times), to locate the country (UK).
  6. Go down the Country column until "France" is heard, (down 2), and back to column 6, (4 cells to the right.
  7. Hear "7.9".

I’ve shortened steps 5 and 6, because you might otherwise have been driven crazy, but they require plenty of key depressions, and at each one that lands on an intervening cell, JAWS starts to announce the cell content, interrupted only by being moved on.

It really is hard work, and can so easily be avoided by marking up header cells properly.

Creating understandable tables

To distinguishe header, (key information), cells from data cells in a simple data table, use <th>, instead of <td>. That’s it, that’s all the web author has to do.

However, the person who creates the table needs to tell you which those key cells are. They know their own data, and are in the best position to decide which row and column needs to be referenced from a data cell to make sense of the table.

You’ll notice that in the example table above, the key information is in column 2. This can happen, visually it’s more logical to have the number or rank of an ordered list of rows in the left-hand column. But the rank, or order isn’t always, or often, the key information.

Let’s see an accessible version of the table.

Accessible example: 2.European pet ownership made up statistics

You still want the number of cat owners in France (Column 6, Row 4).

Rank Country Population (millions) Pet owners (millions) Pet ownership Cat owners (millions) Cat ownership
1 UK 60.36 21.8 36% 10.2 17%
2 Greece 11.33 3.9 34% 2.2 19%
3 France 61.36 20.3 33% 7.9 13%

Now the route to the information is so much easier for JAWS users:

  1. Navigate across the top row to the Cat owners cell (5 depressions of the down arrow key), taking note en route that the Country data is in the second column, not that it’s needed, but the user doesn’t know that yet.
  2. Navigate down the cat owners column (holding down CTRL and Alt, then depressing the down arrow key).
  3. Hear "UK, 10.2", because headers have been coded.
  4. Move down again and hear "Greece, 2.2".
  5. Move down again and hear "France, 7.9".

No unnecessary keystrokes, no audible output of a dozen or more intervening cells while trying to find key data. A much more equivalent browsing experience altogether.

And if the user wants reassurance that they’re in the desired column, querying the JAWS title announcement gives the audible output, "Cat owners (millions): France, 7.9". Nice!

Note: if the first column had been coded as header cells, or no left column cells had been marked up, the audible output would have been as unhelpful as the table without headers. JAWS would announce "Cat owners (millions): 3, 7.9".

So, two steps to making simple data tables simpler to understand:

  1. Get the table creator to identify the key information, (header), row and colum if it isn’t obvious.
  2. Code cells containing key information as header cells using <th>.

Thank you. :)