Accessible Data Tables (2005)
accessibility, Web
Prepared by Roger Hudson For the Web Essential Info Night in Sydney – 30 June 2005
- Data and Layout Tables
- Looking for information
- Screen readers and tables
- Identifying a Table
- Simple Data Tables
- Complex Data Tables
- Very Complex Data Tables
- Keep Tables Simple
- Avoid Columns of Empty Table Cells
- Data Table Accessibility Test
- Conclusion and request
- References and Additional Information
Data and Layout Tables
The table element was introduced with HTML 2.0 in 1994 as a means of presenting data, for example timetables, tabular information about weights, measures, prices etc.
Almost from day one however, Web designers began using table elements to control the layout or presentation of information on a Web page.
And, by the time HTML 3.2 came along, the main use of tables on the web was to control the look of the page rather than the presentation of data in a tabular form.
The use of tables for layout can cause significant accessibility problems and thankfully the work of organisations like the Web Standards Group have seen this use decline in recent times. Complicated layout tables with their masses of cryptic code are no longer cool.
The presentation and layout of web page elements should now be controlled through the appropriate use of cascading style sheets. CSS is the way to go!
This article will discuss;
- How the accessibility of data tables can be improved,
- And, describe a test Russ Weakley and I currently doing into the effective accessibility of different ways to mark up complex data tables.
Many of the examples used in this article are from a web page Russ and I have prepared, which contains data tables using different accessibility markup schemas. A number of people have tested these tables using various assistive technologies and the preliminary results of the tests are presented later in this article.
A quick request and note of caution; please don’t take the examples literally. The content of the tables is very simple, and in some cases we have deliberately made the heading levels much more complex than they need be.
Looking for information
An encounter with the following data table is likely to be three-step process:
- A quick overview to know what the table is about (eg is it a bus timetable, or is it about the prices of vegetables?)
- Is it likely to meet my needs? (Is it about the price of peas in Darwin?)
- Obtain the required detailed information (what is the wholesale price of peas in Darwin?)
Beans | Peas | Carrots | Tomatoes | |
---|---|---|---|---|
Darwin | ||||
Wholesale | $1.00 | $1.25 | $1.20 | $1.00 |
Retail | $2.00 | $3.00 | $1.80 | $1.60 |
Hobart | ||||
Wholesale | $1.20 | $1.30 | $1.00 | $0.80 |
Retail | $1.60 | $2.00 | $2.00 | $1.50 |
With a table like this, most sighted people will achieve the first two steps in almost an instance by looking at the table title and the row and column headings.
For the third task however, they have to locate a particular data cell by looking at row and column headings and using them as reference points.
QUESTION: What is the wholesale price of peas in Darwin?
ANSWER: Easy-peasy for most sighted people: $1.25.
But, what about people with impaired vision who rely on screen readers to use the web and obtain information from data tables?
They can also get the information, if the table is well made and complies with the Web Content Accessibility Guidelines.
Screen readers and tables
At this stage, a quick description of how screen readers interpret data tables is probably worthwhile.
Contrary to the label, most screen readers don’t read the screen. Some screen readers in the past, such as PW Webspeak, did read the screen starting at the top left and reading across the screen from left to right, row by row, down to the bottom right. Screen reading technologies in common use today, including JAWS the most popular screen reader in Australia, read the underlying source code for the page rather than the content on the screen.
JAWS users can have the information in a data table presented in the following ways:
- The whole table can be read line by line, either continuously or with sections selected manually.
- With the keyboard command Atl+Ctrl+Left (or right) Arrow the user can move along rows and JAWS reads out the heading of the actual column plus the content of the cell. Users can also read up and down columns in a similar way.
- With the focus in a particular cell, the keyboard command (Alt+Ctrl+Num Pad 5), will cause JAWS to present the information relating to the selected cell. That is, the cell content and, if the table has been coded correctly, the associated row and column headings.
As can be seen, this approximates the earlier description of how sighted people typically use data tables to obtain information.
Identifying a Table
When you see a data table on a web page it usually has a title or label that identifies the table, for example “Vegetable Prices in Hobart and Darwin”. Also, a quick glance at the table will usually indicate the way it functions, for example products across the top and cities or retailers down the left column.
HTML provides two tags that can help orientate screen reader users and enhance the accessibility of data tables.
<CAPTION>
for the Table Title
The title for data tables you see on the web today are often presented outside the table in a separate heading <h>
or paragraph <p>
element. In some cases they are presented within the table in the top row <tr>
or data cell <td>
. All of these approaches may cause problems for users of assistive technologies.
The <caption>
element is the most accessible way of providing a table with an identifying title. By default, ‘caption’ will place the title in the centre immediately above the table. However, CSS can be used to change the style and on screen position of the ‘caption’ element. For example, the title (caption) can be put underneath the table as is commonly done in scientific and academic publications.
When coding a table, the <caption>
should come immediately after the table element and before anything else.
summary
is not a stand-alone element like caption, but an attribute that is contained within the table element. The contents of the summary
are not displayed on the screen by graphic browsers but can be outputted by screen readers and Braille displays to assist users of these devices to understand the table.
summary
should be used to describe the primary purpose of the table and give an indication of its overall structure. Most assistive output technologies will read the summary
first to provide the user with information to help them interpret and use the table. With more complex tables, the summary
becomes increasingly important.
The following example is part of the code for the “Vegetable Prices in Hobart and Darwin” table:
<table summary="Wholesale and retail prices of vegetables in Hobart and Darwin. There are two levels of row headings.">
<caption>Vegetable prices in Hobart and Darwin</caption>
...
For data tables, identify row and column headers. [Priority 1] For example, in HTML, use TD to identify data cells and TH to identify headers.”
Sighted web users seeking information from a data table, usually scan the headings at the top of each column and the headings at the beginning of each row to identify those that apply to a particular data cell in the table. A relatively easy task that only requires the user being able to determine what is a heading and what is data.
Unfortunately, data tables on the web often use the standard <td>
element for cells that contain both the headings and the data (or information). No problem for the sighted user since they can usually easily differentiate between a cell that contains a heading and one that contains data.
Many assistive technologies however, are unable to differentiate between the two, and will present anything that is contained within <td>
tags as data. As a result, users of screen readers and Braille displays sometimes find it difficulty associating the information in a cell in the centre of a data table with the appropriate column and/or row headings, depending on the technology they use and the complexity of the table.
HTML provides an easy and accessible way of overcoming this problem. The <th>
element should always be used for column and row headings in data tables. (NB: <th>
should never be used with layout tables – Guideline 5.4).
The following table for “plum and pear” prices uses <th>
for the headings.
Black Plums | Bosca Pears | |
---|---|---|
Wholesale | $1.00 | $1.50 |
Retail | $2.00 | $2.50 |
<table border="1" summary="Black plums and bosca pears table with one level of row and column headers">
<caption>Prices for black plums and bosca pears in Sydney</caption>
<tr>
<td></td>
<th>Lemons</th>
<th>Pears</th>
</tr>
<tr>
<th>Wholesale</th>
<td>$1.00</td>
<td>$1.50</td>
</tr>
<tr>
<th>Retail</th>
<td>$2.00</td>
<td>$2.50</td>
</tr>
</table>
A screen reader like JAWS 5 will read the ‘wholesale’ row like this:
“wholesale, dollar one point OO, dollar one point five O”
If the user wants to know the wholesale price of pears, JAWS will voice the selected data cell like this:
“column three, row two, pears wholesale, dollar one point five O”
Abbreviation
The ‘abbr
‘ attribute can be used to provide an abbreviation for long headers so that the entire header is not read out every time. In the example of a simple data table below, ‘abbr
‘ is included in the <th>
tags for the column headings. Some screen readers will then only read the full headings “Black Plums” and “Bosca Pears” the first time they are encountered, and the abbreviations “plums” and “pears” will be read on all the other occasions.
<table border="1" summary="Black plums and bosca pears table with one level of row and column headers">
<caption>Prices for black plums and bosca pears in Sydney</caption>
<tr>
<td></td>
<th abbr="plums">Black Plums</th>
<th abbr="pears">Bosca Pears</th>
</tr>
<tr>
<th>Wholesale</th>
<td>$1.00</td>
<td>$1.50</td>
</tr>
<tr>
<th>Retail</th>
<td>$2.00</td>
<td>$2.50</td>
</tr>
</table>
<thead>
, <tbody>
and <tfoot>
For simple tables, the appropriate use of the <th>
element described above is all that is required to make a table accessible. With just a little more effort however, we can we can further enhance the accessibility of data tables.
HTML provides these elements so that the rows of a table can be grouped together and presented in three different sections;
<thead>
for table head,<tfoot>
for table footer<tbody>
for table body.
<thead>
and <tfoot>
can be used to provide a row of headings at the top and bottom of a table. These are potentially very useful for long tables that extend over more than one page since they enable the header and footer to be printed on each page. Also, with appropriate browser support, they will allow the body of a table to be scrolled independently while the headings remain on the screen. In the future, this is likely to be very useful for users of handheld devices with small screens.
If <thead>
and <tfoot>
are used you must also use <tbody>
to define the body of the table, that is the part of the table that contains the actual data cells. In fact a table can have more than one <tbody>
.
Complex Data Tables
For data tables that have two or more logical levels of row or column headers, use markup to associate data cells and header cells. [Priority 1] For example, in HTML, use THEAD, TFOOT, and TBODY to group rows, COL and COLGROUP to group columns,and the ‘axis’, ‘scope, and ‘headers ‘attributes, to describe more complex relationships among data.”
Tables with single levels of column and/or row headings are significantly easier for screen reader users to understand and use. So wherever possible, complex tables with multiple levels of headings should be avoided.
Sometimes however, complex tables are required. Some data tables, for example scientific tables or those of financial institutions, often require more than one level of row and/or column heading. Once again, most people who are able to access the table visually will not find this a problem. However assistive technologies also need to be able to associate these extra levels of headings with the information contained in the data cells.
The two most commonly recommended ways to mark up tables with two or more levels of headings are:
- Use
id
andheaders
to link data cells with the appropriate headings. - Use
scope
withcol
(and colgroup) and/orrow
(rowgroup) to associate all the cells in a column or row.
But which is the most appropriate?
When testing the accessibility of data tables on websites, I often ask experienced screen reader users to obtain specific information from the tables. In general, most complex data tables prove to be inaccessible. However, when id
and headers
are used appropriately, I have found that the tables tend to be accessible to most screen reader users.
In recent times, I have noticed an increasing use of scope
but in my experience this does not appear to be as successful. I will return to the issue of scope
later when commenting on our test of the different accessibility schemas for data tables.
id
and headers
HTML 4 introduced the ‘headers’ attribute for table cells <td>
. This attribute is used in conjunction with the id
attribute within a table heading <th>
to allow any cell or cells to be associated with a heading or headings.
The following table, which is from the table test page, for orange and apple prices uses id
and headers
.
Imported | Domestic | |||
---|---|---|---|---|
Oranges | Apples | Oranges | Apples | |
Sydney | ||||
Wholesale | $1.00 | $1.25 | $1.20 | $1.00 |
Retail | $2.00 | $3.00 | $1.80 | $1.60 |
Melbourne | ||||
Wholesale | $1.20 | $1.30 | $1.00 | $0.80 |
Retail | $1.60 | $2.00 | $2.00 | $1.50 |
QUESTION: what is the wholesale price of imported apples in Sydney?
The use of id
and headers
means that most people who rely on screen readers will be able to obtain the answer to this question. The source code for part of this table with the relevant id
and headers
highlighted follows:
<table border="1" summary="Wholesale and retail prices of imported and domestic oranges and apples in Sydney and Melbourne. There are two levels of column headings.">
<caption>
Imported and domestic orange and apple prices in Sydney and Melbourne
</caption>
<thead>
<tr>
<td></td>
<th colspan="2" id="imported">Imported</th>
<th colspan="2" id="domestic">Domestic</th>
</tr>
<tr>
<td></td>
<th id="oranges-imp">Oranges</th>
<th id="apples-imp">Apples</th>
<th id="oranges-dom">Oranges</th>
<th id="apples-dom">Apples</th>
</tr>
</thead>
<tbody>
<tr>
<th id="sydney" colspan="5">Sydney</th>
</tr>
<tr>
<th headers="sydney" id="wholesale-sydney">Wholesale</th>
<td headers="imported oranges-imp sydney wholesale-sydney">$1.00</td>
<td headers="imported apples-imp sydney wholesale-sydney">$1.25</td>
<td headers="domestic oranges-dom sydney wholesale-sydney">$1.20</td>
<td headers="domestic apples-dom sydney wholesale-sydney">$1.00</td>
</tr>
<tr>
<th headers="sydney" id="retail-sydney">Retail</th>
...THE REST OF THE TABLE CODE ...
Using a combination of JAWS keyboard commands, most users will be able to locate the cell that is likely to contain the information they require. They can confirm this is the correct cell by asking JAWS to “say the current cell”.
If the focus is on the appropriate cell ($1.25), JAWS will “say the current cell” like this:
“column three, row four, apples Sydney wholesale imported, dollar one point two five”
Very Complex Data Tables
The table test page contains the following data table about cherry and apricot prices, which has three levels of column headings and two levels of row headings that use id
and headers
.
Imported | Domestic | |||||
---|---|---|---|---|---|---|
Apricots | Cherries | Apricots | Cherries | |||
A Grade | B Grade | A Grade | B Grade | |||
Perth | ||||||
Wholesale | $1.00 | $9.00 | $6.00 | $1.20 | $13.00 | $9.00 |
Retail | $2.00 | $12.00 | $8.00 | $1.80 | $16.00 | $12.50 |
Adelaide | ||||||
Wholesale | $1.20 | N/A | $7.00 | $1.00 | $11.00 | $6.00 |
Retail | $1.60 | N/A | $11.00 | $2.00 | $13.00 | $10.00 |
QUESTION: What is the wholesale price of imported A-grade cherries in Perth?
Sections of code for the cherry and apricot table follows with the relevant id
and headers
highlighted.
<thead>
<tr>
<td></td>
<th id="imp" colspan="3">Imported</th>
<th id="dom" colspan="3">Domestic</th>
</tr>
<tr>
<td></td>
<th headers="imp" id="imp-apr">Apricots</th>
<th headers="imp" id="imp-che" colspan="2">Cherries</th>
<th headers="dom" id="dom-apr">Apricots</th>
<th headers="dom" id="dom-che" colspan="2">Cherries</th>
</tr>
<tr>
<td></td>
<td></td>
<th headers="imp imp-che" id="imp-che-agrade">A Grade</th>
<th headers="imp imp-che" id="imp-che-bgrade">B Grade</th>
<td></td>
<th headers="dom dom-che" id="dom-che-agrade">A Grade</th>
<th headers="dom dom-che" id="dom-che-bgrade">B Grade</th>
</tr>
</thead>
... MORE CODE ...
<tbody>
<tr>
<th id="perth" colspan="7">Perth</th>
</tr><tr>
<th headers="perth" id="perth-wholesale">Wholesale</th>
<td headers="imp imp-apr perth perth-wholesale">$1.00</td>
<td headers="imp imp-che imp-che-agrade perth perth-wholesale">$9.00</td>
<td headers="imp imp-che imp-che-bgrade perth perth-wholesale"> $6.00</td>
<td headers="dom dom-apr perth perth-wholesale">$1.20</td>
... THE REST OF THE TABLE CODE ...
Although the heading structure of this table is complex, by using a combination of keyboard commands, most JAWS users will be able to locate the cell that is likely to contain the information they require.
With the focus on the appropriate cell ($9.00), JAWS will “say the current cell” like this:
“Row five, column three, imported Perth wholesale cherries A grade, dollar nine point O O”
Keep Tables Simple
As indicated already, multiple levels of column headings can disorientate screen readers users. For example, when JAWS encounters the cherry and apricot table above it will voice:
“table in seven columns and nine rows” (followed by the general table information,
summary
etc).
The three rows containing column headings are introduced as follows:
- “three columns row one …”
- five columns row two …”
- seven columns row three …”
There is no indication that these rows contain column headings. Also, users may be left is some doubt about the number of columns in the table. The inclusion of ‘headers’ attributes in the lower levels of column headings (as indicated in the source code above) does allow the different heading levels to be associated when the user asks JAWS to “say the current cell”.
In addition, some preliminary results from the table test page suggest Braille devices can have significant problems with multiple column and row headings.
Wherever possible simple tables should be used; they are easier to code and much easier for people who rely on screen readers to use.
Avoid Columns of Empty Table Cells
Developers sometimes use columns of empty header and data cells to provide a space between the columns in a table.
JAWS, for example, voices the word “blank” every time it encounters an empty cell and this can reduce both the usability and accessibility of data tables for people who rely on screen readers.
CSS rather than empty cells should be used to control the presentation of data tables.
Data Table Accessibility Test
Russ Weakley and I have prepared the Data Table Accessibility Test page to test different ways data tables can be marked up to make them accessible to users of screen readers and Braille devices. The page contains four tables, one simple data table and three complex data, which have more than one level of column and row heading.
We have asked interested people to test these tables with assistive technologies and send us their comments on the accessibility of the different tables.
We are very grateful for the useful feedback we have received from:
- Andrew Downie
- Roger Johansson
- Patrick Lauke
- Bruce Maguire
- David Woodbridge
But we would like more.
If you are interested in contributing, the test tables can be found at: http://www.usability.com.au/resources/tabletest.cfm.
Two of the complex data tables on the test page use id
and headers
to associated column and row headings with data cells. Another table uses scope
with col
and row
to associate all the cells in a column or row.
At this stage the tables have been tested with the following screen readers:
- JAWS Versions, 4.02, 5.1, 6.0 and 6.2 (JAWS is the most popular screen reader in Australia).
- Window-Eyes 5.0.
- Connect Outloud 2.0.
All these screen readers could effectively access the two complex data tables that use id
and headers
. The JAWS results with these tables have already been described in this article. Screen reader support for scope
however was patchy.
scope
, col
and row
The use of scope
, in association with col
and colgroup
, is often promoted as an effective way of grouping the headers and information in a column in order to enhance accessibility. Using scope
with row
and rowgroup
is sometimes also suggested, although there is some ambiguity about how this should be done and the advantages in terms of improved accessibility.
The table test page contains the following “Brass and steel nuts and bolts” table, which uses scope
, col
and row
. (I generally don’t use scope
, so please let me know if the way scope
is used in this table is not correct.)
Brass | Steel | |||
---|---|---|---|---|
Bolts | Nuts | Bolts | Nuts | |
10cm | ||||
Wholesale | $1.00 | $1.25 | $1.20 | $1.00 |
Retail | $2.00 | $3.00 | $1.80 | $1.60 |
20cm | ||||
Wholesale | $1.20 | $1.30 | $1.00 | $0.80 |
Retail | $1.60 | $2.00 | $2.00 | $1.50 |
QUESTION: What is the wholesale price of 10cm brass nuts?
The following section of source code for this table indicates what I believe is the way the scope
, col
and row
attributes are used to provide the answer to this question.
<table border="1" summary="Wholesale and retail prices for 10 and 20 centimetre brass and steel nuts and bolts. There are two levels of column headings.">
<caption>Prices of Brass and Steel nuts and bolts</caption>
<colgroup>
<colgroup span="2">
<colgroup span="2">
<thead>
<tr>
<td></td>
<th scope="colgroup" colspan="2">Brass</th>
<th scope="colgroup" colspan="2">Steel</th
</tr>
<tr>
<td></td>
<th scope="col">Bolts</th>
<th scope="col">Nuts</th>
<th scope="col">Bolts</th>
<th scope="col">Nuts</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="rowgroup" colspan="5">10cm</th>
</tr>
<tr>
<th scope="row">Wholesale</th>
<td>$1.00</td>
<td>$1.25</td>
<td>$1.20</td>
<td>$1.00</td>
</tr>
<tr>
<th scope="row">Retail</th>
... THE REST OF THE TABLE CODE ...
It does not appear possible for a screen reader user to obtain the “wholesale price of 10cm brass nuts” from this table, which is marked up using scope
.
With the focus on the appropriate cell ($1.25), JAWS 5.1 will “say the current cell” like this:
“column three, row four, brass wholesale, dollar one point two five”
NB: the “10cm” size and “nuts” headers are not voiced.
With JAWS 6.2 the result is:
“column three, row four, brass nuts wholesale, dollar one point two five”
NB: the “10cm” size header is still not voiced. I am not very experienced in the use of scope
and would greatly appreciate feedback about the way “Brass and Steel Nuts and Bolts” table has been coded.
Windows-Eyes does not appear to support scope
.
Conclusion and request
First, I would like to once again stress the importance of making data tables as simple as possible. Data tables with more than one level of headers are harder to code and much harder for people who rely on assistive technologies to use.
At this stage, it appears that id
and headers
are the most effective way to make complex data tables accessible. Although id
and headers
are slightly more difficult to code than scope
, the apparent poor screen reader support for scope
means that this is probably not an effective accessibility option.
Finally, a request, if you have the time please check out the Data Table Accessibility Test page and if possible test it with different technologies. I would be very grateful for any feedback on the quality of the code used for the tables on the page and how well screen readers and Braille devices can access them.
References and Additional Information
BOOKS
- Clark, Joe. 2003. “Building Accessible Websites” New Riders Publishing, Indiana.
- Paciello, Michael. 2000. “Web Accessibility for People with Disabilities”, CMP Books, Kansas.
- Slatin, John and Rush, Sharon. 2003. “Maximum Accessibility”, Addison-Wesley, Boston.
WEBSITES
- World Wide Web Consortium. “Web Content Accessibility Guidelines 1.0.“
- Thatcher, Jim. “Web Accessibility for Section 508“.
- Byrne, Jim. “Table Manners: Creating accessible Tables for both layout and data“.
- Webaim. “Creating Accessible Tables“
- Ferg, Stephen. “Techniques for Accessible HTML Tables“