Introduction
Most of us are aware of the problems that table based layouts can cause. They make it hard or costly to rebrand or restructure. They make pages overly large, costing more in bandwidth charges, and making it difficult for people on slow connections to load the page. And more importantly, they make pages very hard to navigate for blind/visually impaired, or disabled users, as the table structures don't make much sense when not displayed in a visual context. And many of us have managed to get away from tables for our layouts.
But the thing is that tables were invented for a reason. For displaying tabular data. A set of results, or a comparison table, or anything else that when displayed belongs in a table.
Since we still need to use tables occasionally, we also need a way of making sure that the tables still make sense to our blind/visually impaired, or disabled visitors. As most data tables contain a large amount of data, we need some way to help them understand what bit of data belongs where.
Take this basic table. In a visual environment, the visual positioning of the data would make enough sense for most of us to understand.
<table>
<tr>
<td rowspan="2">Browsers</td>
<td rowspan="2">Op</td>
<td colspan="2">Gecko</td>
<td rowspan="2">Saf</td>
<td rowspan="2">IE</td>
</tr>
<tr>
<td>FF</td>
<td>Moz</td>
</tr>
<tr>
<td>Browser</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Email</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>IRC</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
</table>
Browsers | Op | Gecko | Saf | IE | |
FF | Moz | ||||
Browser | Yes | Yes | Yes | Yes | Yes |
Yes | No | Yes | No | No | |
IRC | Yes | No | Yes | No | No |
If a blind person were to read this with a Braille reader, or with a speech reader, it would appear like this:
Browsers Op Gecko Saf IE FF Moz Browser Yes Yes Yes Yes Yes Email Yes No Yes No No IRC Yes No Yes No No.
Clearly this would be no help at all. So we need to make the structure more obvious. So there is something that the Braille or speech reader can identify and hopefully convay some meaning to the user.
Many speech readers are available for general screen reading (JAWS and Dragon Naturally Speaking are popular ones, and the Mac Operating System has its own inbuilt screen reader). New to the field but with a distinct difference is Opera 7.6+. Unlike the releases for other platforms, the Windows 2000/XP release is able to receive spoken commands and read normal web pages. But what makes it unique is that not only can it interact with VoiceXML pages, but it can also understand speech and aural CSS.
Unfortunately, because of this different focus, Opera does not immediately make use of the accessibility features of tables, but because of Opera's high level of CSS support, you can use CSS to allow it to make use of them. Since I am sure you probably don't want to have to go to all that work yourself, I have done all the work for you. This page is fitted with my speech enabled 'Spoken Table' stylesheet. Feel free to download it and use it on your own pages or as a user stylesheet, subject to my usual terms of use. Opera 7.6+ users, you can enable it right now using View - Style - Spoken Table.
Table Headings
The first thing to do is to make all headings obvious. This is as simple as replacing all <td> tags with <th> tags on heading cells.
<th>Browser</th>
<td>Yes</td>
<td>Yes</td>
Browsers | Op | Gecko | Saf | IE | |
---|---|---|---|---|---|
FF | Moz | ||||
Browser | Yes | Yes | Yes | Yes | Yes |
Yes | No | Yes | No | No | |
IRC | Yes | No | Yes | No | No |
Heading scope
Although this has little or no effect in a visual environment, a Braille or speech reader can use this information to tell the user if this heading is a row heading or column heading. This in turn will enable them to make more sense of the rest of the table.
<th scope="row">Browser</th>
<td>Yes</td>
<td>Yes</td>
Browsers | Op | Gecko | Saf | IE | |
---|---|---|---|---|---|
FF | Moz | ||||
Browser | Yes | Yes | Yes | Yes | Yes |
Yes | No | Yes | No | No | |
IRC | Yes | No | Yes | No | No |
Heading titles
I have used abbreviations in the table headings. Seeing this in a visual context, these may make sense. They are unlikely to make so much sense in a non-visual environment. Adding a title attribute allows the Braille or speech reader to explain what the abbreviation means. As an extra bonus, the title is usually shown by visual browsers when the user holds their mouse cursor over the header.
<th title="Internet Relay Chat" scope="row">IRC</th>
<td>Yes</td>
<td>No</td>
Browsers | Op | Gecko | Saf | IE | |
---|---|---|---|---|---|
FF | Moz | ||||
Browser | Yes | Yes | Yes | Yes | Yes |
Yes | No | Yes | No | No | |
IRC | Yes | No | Yes | No | No |
Heading abbreviation
This attribute provides an appropriate abbreviation of the heading, if the heading is significantly long. The abbreviation can be used instead of the normal heading content to save space in visual tables, or inserted before all applicable data cells by a speech or Braille reader to make it more clear which header they relate to.
I have seen this abused (and even recommended) as a way to say the full header content if the header content itself is abbreviated. That is not the right way to do it. If the header content is an abbreviation, you should use the title attribute to explain it. The abbr attribute should only be used to provide an appropriate abbreviation of a header.
Note: My stylesheet does not make use of these, and will use the full header content instead. As a result, I will not use this attribute in any further examples, but you may still want to use it if it is appropriate for your tables. Other speech readers (such as Home Page Reader) will use this abbreviation if it is provided.
<th abbr="W3C">World Wide Web Consortium</th>
Captions and summaries
The caption is typically used to label the table, giving a quick title in both visual and non-visual browsers. For non-visual browsers, it is also useful to provide a table summary. This enables the user to read or hear a description of the information that the table will provide, so that they can easily tell if they want to skip that table and continue beyond it. Something most visual based users take for granted.
<table summary="A list of the most common browsers detailing what other application components they contain">
<caption>Table 5 - browser components</caption>
Browsers | Op | Gecko | Saf | IE | |
---|---|---|---|---|---|
FF | Moz | ||||
Browser | Yes | Yes | Yes | Yes | Yes |
Yes | No | Yes | No | No | |
IRC | Yes | No | Yes | No | No |
id and headers attributes
If we assign an ID to each heading, then we can set the headers attribute on the table cells. This allows a Braille or speech reader to not only give the contents of the cell, but also say what headings it applies to. More advanced readers will be able to say the associated header content, but some will only be able to say the contents of the headers attribute, so try to make sure that the IDs make sense on their own. To keep your document valid, the IDs should be unique within your document. Since I am repeating my example, I have not done this, so this document will not validate.
<th id="Opera" title="Opera" scope="col" rowspan="2">Op</th>
...
<th id="Browser" title="Web browser" scope="row">Browser</th>
<td headers="Opera Browser">Yes</td>
Browsers | Op | Gecko | Saf | IE | |
---|---|---|---|---|---|
FF | Moz | ||||
Browser | Yes | Yes | Yes | Yes | Yes |
Yes | No | Yes | No | No | |
IRC | Yes | No | Yes | No | No |
Categories
Sometimes, table contents fit into categories that cannot be easily defined within the column structure. Each table cell or heading may accept the axis attribute. In theory this could be queried, giving a summary of information within the given category. However, since most browsers have no way of displaying this except using scripts, I do not recommend its use. However, Braille or speech readers may have a way to read it, so you can still use it if you want to.
<th axis="Internet suite" id="Opera" title="Opera" scope="col" rowspan="2">Op</th>
Browsers | Op | Gecko | Saf | IE | |
---|---|---|---|---|---|
FF | Moz | ||||
Browser | Yes | Yes | Yes | Yes | Yes |
Yes | No | Yes | No | No | |
IRC | Yes | No | Yes | No | No |
thead, tbody and tfoot
Splitting a table heading up into sections has numerous purposes. Visual browsers are allowed to scroll table bodies while leaving the header and footer in place on the page. The header and footer can be printed on each page of a printed table spanning multiple pages. But more usefully for accessibility, it helps a Braille or speech reader identify whether the current block of data is the header section, body section or footer section of the table. Just one more way to help non-visual users make sense of tables.
(Unfortunately, Opera makes the small mistake here of reading the summary after reading the table when using my Spoken Table stylesheet. This is due to a bug with generated content positioning. I have reported it, so hopefully it will be fixed soon.)
<thead>
<tr> ... </tr>
...
</thead>
<tbody>
<tr> ... </tr>
...
</tbody>
Browsers | Op | Gecko | Saf | IE | |
---|---|---|---|---|---|
FF | Moz | ||||
Browser | Yes | Yes | Yes | Yes | Yes |
Yes | No | Yes | No | No | |
IRC | Yes | No | Yes | No | No |
To summarise ...
Including all of these techniques would probably be going a little overboard, but the more you can use, the easier you will make things for visitors who are unable to use a visual medium for viewing web pages. You can use my 'Spoken Table' stylesheet to make it even easier for them to make sense of the table confusion. If you are a user who has accessibility problems with tables, you can use my stylesheet as a user stylesheet in Opera 7.6. Enjoy, and let's help keep the web open to people who have different requirements to ourselves.
Links
- Accessibility
- Making accessible pages
- Making accessible tables - you are here