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
<caption> for the Table Title
summary for Table Purpose
Simple Data Tables
Abbreviation
<thead>, <tbody> and <tfoot>
Complex Data Tables
id and headers
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?)
Vegetable prices in Darwin and Hobart 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 for Table Purpose
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>
...
Simple Data Tables
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."
Web Content Accessibility Guideline 5.1
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.
Prices for black plums and bosca pears in Sydney
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."
Web Content Accessibility Guideline 5.2
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 and headers to link data cells with the appropriate
headings.
Use scope with col (and colgroup) and/or row (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 and domestic orange and apple prices in
Sydney and Melbourne 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 and domestic cherry and apricot prices in
Perth and Adelaide 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.)
Prices of Brass and Steel nuts and bolts 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"