HTML tables on the web come in two varieties, layout tables and data tables.
There is no question that the vast majority of tables on the web are layout tables, used to structure the visual appearance of the page. Often the structure of tables is remarkably complex, with tables nested in tables as much as seven deep.
In the Navigation section (Section 4) of this tutorial we talked a little bit about how tables are read, or linearized, independently of how complex those tables are. At least the definition of the linearization algorithm is simple. Lay out the text a line at a time starting with the first cell of the first row; then move across the columns of the first row, then proceed to the second row, and so on. If you come to a table in that process, linearize it and then continue. Another description of linearzation is "source code order." If you look at the source code of a page, and remove all the table tags (<table>, <tr>, <td> <th>, etc.) then the resulting text is the linearized version of the table. Finally, if you want an easy technique to see the way tables are spoken, look at a site that uses tables for layout, and apply the Linearize function in the Tables menu of the web Accessibility Toolbar (Section 3).
You should make sure that your pages make sense when linearized in this fashion. As we discussed in Section 3, one of the simplest views of your page in linear form is provided by the "lynx view," a rendering of the page as if you were using the Lynx text browser. This Delorie software Lynx Viewer site, http://www.delorie.com/web/lynxview.html, provides you the opportunity of seeing your page as if the browser were Lynx. Or you can use the Web Accessibility Toolbar (see Section 3), Check > Lynx Viewer. Usually the page will make sense.
Unless, that is, one or more of your tables is really a data table, because, while layout tables usually linearize well, data tables do not.
So what are data tables? How are they distinguished from layout tables? Data tables present things like financial results, rainfall totals by city and month, TV listings or bus schedules. What do these have in common? What is common is that the meaning of data in most cells of the table depends on heading information, which is usually in the first row and the first column of the table. You cannot know what the data means unless you are aware of the contents of the corresponding headings.
For layout tables, information in various cells stands on its own. There are no headings— just table cells containing text and images. In contrast, headings are crucially important for understanding (or reading) data tables. That is the problem! Your tables must be designed and marked up in such a way as to ensure that assistive technology will know where the headings are and be able to announce them.
Think of a TV listing -- for example, TV Guide (http://tvguide.com/listings/):
Screen shot of TV listings
Here is part of the text view of this table from IBM Home Page Reader, starting at the time indicator (and Heading), 7:30:
7:30 PM 8:00 PM 8:30 PM 2 KTBC American Juniors Paradise Hotel 3 KVUE George Lopez (Repeat) Drew Carey Drew Carey Dating Experiment> 4 KXAN <Fame Law & Order (Repeat) 5 KEYE <60 Minutes II Perfect Murder, Perfect Town (Repeat) 6 INFO <Information Channel Information Channel 8 HSN <24 Hour Jewelry Celebration 24 Hour Jewelry Celebration 9 KLRU <Ken Burns American Stories (Repeat) West Point (Repeat) 10 TBN International Intelligence Briefing Gaither Homecoming Jack Van Impe Presents
When you read this, you will find that important information, represented by the tabular structure, is lost. Because of spanned cells, there is no way to even guess the time slot for a program, even if you did remember the headings. Imagine searching for a program title and then trying to figure out at what time and on what channel it will be aired. Nearly impossible!
This financial data table from Fidelity.com (http://www.fidelity.com/) has similar problems. Just imagine starting to read this table in the middle. It is hard enough to remember the column headings, let alone keep track of them as you view numeric data one cell at a time.
Remember that visually you can quickly glance at row and column headers to understand a piece of data; you can't do that when you are reading the table linearly.
There are a number of constructs in HTML 4.0 that contribute to making data tables accessible, that contribute to making it possible or listen to and understand a table. These are thoroughly discussed in the Tables section of the HTML 4.0 document, http://www.w3.org/tr/html4/struct/tables.html.
We will discuss the three most important techniques for giving assistance to those with disabilities who are trying to interpret tabular information.
caption element and the
If you can see web page and you come across a data table, you naturally and automatically scan that table to get a quick sense of what the table presents. But some users have difficulty making that analysis, or simply cannot because they listen to the contents of the display rather than look at it. There are two techniques to help those users.
caption element provides the web developer with a standard way of programmatically associating the title
of the table with the table itself. The caption can appear at the top or bottom of the table. Even such a simple label
can help orient a user to table content. And having it programmatically attached to the table means that screen readers
will announce that as the table is encountered.
|Caesar||Chicken Divan||Chocolate Mousse|
A simple table with a caption
The simple table above has a caption, "Today's Lunch Menu," which explains the table contents. After hearing this caption, reading the three heading cells and three data cells would make (more) sense.
The following is the code for that table. Note the
caption element directly after the
To move the caption to the bottom of the table, place the
caption element just before the end table tag (
<table border="1" cellpadding="0" > <caption>Today's Lunch Menu</caption> <tr> <th>Salad</th> <th>Entree</th> <th>Dessert</th> </tr> <tr> <td>Caesar </td> <td>Chicken Divan</td> <td>Chocolate Mousse</td> </tr> </table>
Because we know how assistive technology reads a table, we also know that this table would be organized better with its headings down a column, like this:
Lunch menu reads better
It then would read naturally (thanks to Home Page Reader):
Today's Lunch Menu Salad Caesar Entree Chicken Divan Dessert Chocolate Mousse
When a table is more complicated, web authors are encouraged to use the
summary attribute of the
table element. This, like the
longdesc attribute for images, is not represented visually. It is rendered from the HTML code by assistive technology like screen readers and talking browsers.
summary attribute should contain a summary of the way the table is laid out - not a summary of the results.
It should provide an orientation for someone who listens to the table.
|Class of Service||Appetizer||Salad||Wine||Entree||Dessert|
|Economy||Peanuts||None||Complimentary Soft Drinks, Liquor for Purchase||Ham and Cheese Sandwich||Packaged Cookies|
|Business||Shrimp Cocktail||Mixed Greens||Oceana Label Chardonnay or Merlot||Chicken Satay or Beef Tips||New York Style Cheesecake|
|First||Beluga Caviar||Caesar, Salad Nicoise, or Antipasto||Vive Clicquot Vintage Reserve 1990||Salmon Basil Cream, Raspberry Balsamic Chicken, Boeuf En Daube||Assorted Belgian Truffles|
Oceana Airlines dinner service
For this Dinner Service table the
table element with its
summary attribute looks like this.
<table border=1 summary="This table of Oceana Airlines dinner service gives the five dinner courses (column headings) for each class of service, Economy, Business, and First (row headings)">
With that summary, a person who is using a screen reader will have an overview of the table layout before he starts to read it.
Using Column and Row Headers
The techniques for dealing with data tables that we discussed so far are designed to give an overview of the table. These are not required by the Section 508 Standards. The next two techniques deal with the internals of the table. These techniques will enable you to satisfy the following two Section 508 Standards:
Row and column headers shall be identified for data tables.
Markup shall be used to associate data cells and header cells for data tables that have two or more logical levels of row or column headers.
Let's look first at §1194.22(g) that requires that you, in effect, label table headers as html headers (
- not unlike what we talked about in the Navigation Section (Section 4) where heading text
should be marked up as HTML headings (
Each table cell is either a pure data cell (
td) or a header cell (
th). By default, headers will
appear centered in bold so that most users can easily identify them. If this is not exactly the way you want your headers
to appear, you can modify their appearance using style sheets (see Section 11). By labeling a cell as a
th, you are identifying it as a table header as required by §1194.22 (g).
In addition to making the headers stand out, they can be identified by assistive technology so that when a talking browser is reading a specific cell it can, on command, search for the header cells and announce them. In addition, as the user moves from cell to cell, the assistive technology will announce the row and column headers that have changed. For example, moving across the Business class row in the Oceana Airlines Dinner Service table above, a screen reader user would hear, "Appetizer, Shrimp Cocktail, Salad, Mixed Greens, Wine, Oceana Label Cardonnay or Merlot, Entree, Chicken Satay or Beef Tips, Desert New York Style Cheesecake."
Both the Lunch Menu table and the Oceana Dinner Service table above have headers specified as they should be. You can
see those headers (
th) in the HTML code for the Lunch Menu Table. You can also use the Web Accessibility Toolbar,
Tables > Table headers; this will put a black background
on all cells which are table header cells (
The Oceana Dinner Service table is a little different because of the ambiguity of whether the top left cell is a header
for its column or its row. This is resolved using the
scope attribute on that
th cell, or, as
is recommended by many, on every
th cell. The possibilities are
scope="col" (which is appropriate
for that top left cell) or
scope="row". Here is the code for the first two rows of the Dinner Service table.
<tr> <th scope="col">Class of Service</th> <th>Appetizer</th> <th>Salad</th> <th>Wine</th> <th>Entree</th> <th>Dessert</th> </tr> <tr> <th>Economy</th> <td>Peanuts</td> <td>None</td> <td>Complimentary Soft Drinks, Liquor for Purchase</td> <td>Ham and Cheese Sandwich</td> <td>Packaged Cookies</td> </tr>
The coding for this table has evolved since it first appeared in Mike Paciello's book (Paciello,
Michael G., Web Accessibility for People with Disabilities, Lawrence, Kansas: CMP Books, 2000);
id markup (more about that later) which is not necessary. The earlier version
of this course included the
scope attribute on all cells, not just the one cell whose scope is ambiguous.
When you are using
th cells, assistive technology knows they are headers and can deduce the scope; so the
scope attributes are not necessary.
With the table marked up this way, a screen reader would announce the cells in the second row something like this: "Appetizer, Peanuts; Salad, None;" etc.
Alternative to using header cells (
th) with the
scope to resolve
ambiguity, you can use data cells (
td) with the
scope attribute on any cell
that is a heading. This technique has the advantage that you don't have to go back and restyle the heading text. Any cell
is a heading if it is a
th or it is
td with a
The final technique for making tables accessible is the most rigorous and programmatic. HTML 4.0 introduced the
for table cells. With the
headers attribute you can specify any other cell or cells as the heading information
for a given (data) cell.
The idea is simple. You attach an
id attribute to any cell you want to be a header cell. Then, add the id's of each header cell to the
headers attribute of a data cell.
For a simple case, let's say the id's of the column headers are c1, c2, c3, and c4 and the id's of the row headers are r1, r2, r3, and r4. Then the cell at row 3, column 2 would have
headers="r3 c2" or the other way around,
headers="c2 r3" if that sounded better.
In the "rectangular examples" above, assistive technology can figure out which is the header information. But in a table like the Travel Expense Report that follows, that is nearly impossible. (This table is from the Web Accessibility Initiative, Techniques for Web Content Accessibility Guidelines 1.0 (http://www.w3.org/TR/WCAG10-HTML-TECHS/) - tables are discussed in Section 5 of that techniques document.)
Here is sample HTML mark up for the data cells of this table using the
headers attribute. I have used the convention that
c3, ... are the
id's of the column headings and
r3, ... are the
id's of the row headings.
<table border="1"> <caption>Travel Expense Report</caption> <tr> <td></td> <th id="c2">Meals</th> <th id="c3">Hotels</th> <th id="c4">Transport</th> <td id="c5">subtotals</td></tr> <tr> <th id="r2">San Jose</th> <td></td><td></td><td></td><td></td> </tr> <tr> <td id="r3" >25-Aug-97</td> <td headers="c2 r2 r3" bgcolor="#ffff00">37.74</td> <td headers="c3 r2 r3">112.00</td> <td headers="c4 r2 r3">45.00</td> <td></td></tr> <tr> <td id="r4">26-Aug-97 <td headers="c2 r2 r4">27.28</td> <td headers="c3 r2 r4">112.00</td> <td headers="c4 r2 r4">45.00</td> ... <tr><th id="r10">Totals</th> <td headers="c2 r10">196.27</td> <td headers="c3 r10">442.00</td> <td headers="c4 r10">162.00</td> <td headers="c5 r10">800.27</td></tr> </table>
The highlighted cell with the value 37.74, for example, is associated with the date "25-Aug-97" (
id="r3"), the city "San Jose," (
id="r2") and expense item "Meals" (
id="c2"). To make it readable, the subject cell is coded:
<td headers="c2 r2 r3">37.74</td>
Assistive technology might then read this cell "Meals, San Jose, 25-Aug-97, 37.74" or "37.74 ,Meals, San Jose, 25-Aug-97."
In terms of money and workload, implementing accessible tables can be an expensive proposition. That expense
can be reduced with careful design of data tables. If a table with 10 rows and 10 columns requires
id markup then all 100 cells must be specially coded. For simple tables, about 18 cells
need special attention and what is done is repetitive which it is not true for the
Here is a summary of the techniques for accessible tables:
captionelement as a title for the data table and and/or use the
summaryattribute to give a brief overview of the structure of the table.
- And markup all table header cells
- Use the table header element,
th, for all header cells and add the
scopeattribute when that scope is ambiguous (corners).
- Or use
tdtogether with the
scopeto specify header cells
- Or use
idattributes on the header cells and the
headersattribute on the data cells to explicitly associate header information with data cells. This is essential if there are data cells whose header information is not in the same row and the same column as that cell.
- Use the table header element,
- And do not use any of the accessible data table markup (
summary) on a table used for layout. In particular, avoid gratuitous announcements resulting from
summary="This table used for layout"
If you have comments or questions on the content of this course, please contact Jim Thatcher.
This course was originally written for the Information Technology Technical Assistance and Training Center, funded in support of Section 508 by NIDRR and GSA at Georgia Institute of Technology, Center for Rehabilitation Technology. The course has been completely revised.