Skip to page content or skip to Accesskey List.
Search evolt.org
evolt.org login: or register

Work

Main Page Content

Building accessible tables.

Rated 4.02 (Ratings: 20) (Add your rating)

Log in to add a comment
(25 comments so far)

Want more?

 
Picture of wiseguysonly

Tim Roberts

Member info | Full bio

User since: August 17, 2002

Last login: August 17, 2002

Articles written: 3

CSS and XHTML have given tables a pretty rough ride in recent times. Of course, this is the fault of just about all web developers who have at some point in their career used them for laying out page elements. This article is not about using tables for layout. It is about how to use tables to display information in an accessible manner. Use XHTML and CSS all you want for layout, but at the end of the day (if there is one on the internet) so long as there are informational relationships there will be tables. In fact, to attempt to display any of complex information relationships without a table is a mistake. If you have information to display, use tables and use them well.

Table Basics

If I create a plan of what I intended to achieve yesterday and place it in a table, to a sighted user it can be a great aid:

Today's action plan:
Time Planned Task Preferred Task What I actually did
10 - 12 Catch up on replying to my emails. Have a lie in. Surfed aimlessly.
12-1 Have Lunch. Have Lunch. Had Breakfast.
1-5 Finish that project. Go to video store. Caught up on my emails.

Blind and other severely vision impaired users rely on assistive technologies to render web content. All text can be fed through a screen reader or refreshable braille display to be presented to the user. However, despite containing text, the table above could make a real mess of things without a few extra behind the scenes accessibility enhancements. To an assistive browser our table could well look like this:

Time Planned Task Preferred Task What I actually did
10 - 12 Catch up on replying to my emails. Have a lie in. Surfed aimlessly.
12-1 Have Lunch. Have Lunch. Had Breakfast.
1-5 Finish that project. Go to video store. Caught up on my emails.

Ok, we can still kind of make a little sense of it. That is because we can see it. A blind user can't easily scan back up and check what the third piece of information relates to. Was it what I actually did, or what I would have preferred to do? This is why we need to create relationships within the code of our table. Thankfully, from HTML4.0 a bucketful of accessibility enhancements were introduced to enable the conscientious developer to do this.

Before we see how this is done let's go back to first grade. A table is created with a table element. Everything in the table is contained between <table></table>. Beneath this we can place rows with the <tr></tr> element. Each row can have any number of cells using the <td></td>. Rows can alternatively contain the header element, <th></th>, which we will see are basically fancy cells with allow us to add turbo-charged accessibility to our table.

Phew, you are still here.

Explaining Our Table

The first thing we should include in any table is a caption and a summary. The caption will be visible to all users, the summary is a bit of hidden code for special browsers. The caption comes right under the opening table tag:

<table><caption>Today's action plan: </caption>...

It should provide the user with a succinct and straight to the point description of the table's content. The caption will be rendered on the screen when your document is accessed so keep it simple but coherent.

The summary is a place to guide non-visual agents and is an attribute taken by the opening table tag. Here you can describe the table in a bit more detail especially with regards to structure:

<table summary ="This table charts my activities for the day
  based on three criteria for each of three periods of the day: What I was supposed
  to so; what I would have preferred to do and what I actually did. ">...

Our table makes much more sense now to a blind user. Actually, she can probably figure out what it should look like. Many visually impaired users actually prefer to be labeled "vision impaired". Just because they can't see, it doesn't mean they can't visualize! Another point to keep in mind is that the summary attribute is not rendered on screen, so we can have the time of our life with it. We just need to make sure that what we write in there is relevant and provides assistance. Don't write all of the table data in there, just describe the relationship of data in the table.

Relationship advice.

Now we know what our table is about, we need to show the browser how information is related. This will help us overcome the problem of of information being rendered in continuous and seemingly unstructured lines. This is where we go to work with our table headers. The table above has 4 cells (or columns) per row, so we will need to add 4 headers to show what these columns represent. The best place for headers is in our first row, right below the <caption></caption> element:

Here is what it looks like for the table above:

<tr>
  <th id="h1">Time.</th>
  <th id="h2">Planned Task</th>
  <th id="h3">Preferred Task.</th>
  <th id="h4">What I actually did.</th>
</tr>

Notice that each <td> tag has taken an attribute called id which has a unique identifier. I will show you now how we use these unique identifiers to create relationships for the information in our table, and what the outcome is. We now need to link all of our columns containing the data to their appropriate header. Look how easy this is by looking at the first row of data from the table above:

<tr>
  <td headers="h1">10 - 12</td>
  <td headers="h2">Catch up on replying to my emails.</td>
  <td headers="h3">Have a lie in.</td>
  <td headers="h4">Surfed aimlessly.</td>
</tr>

What we have done here is created a link between a piece of information and its header by incorporating a headers attribute into each cell that refers to the relevant id we created in our &lt;th&gt; id attribute. All we need to do is make sure we include the same references in every row we create in our table. So its not even difficult to achieve with dynamic output from a scripted page such as one produced with asp or php. But what does all that extra stuff do. The best way to explain is to show you how a screen reader would deal with that information. Here is the output for our example row as seen by a screen reader:

Time: 10 -12
Planned task: Catch up on replying to my emails.
Preferred Task: Have a lie in.
What I actually did: Surfed aimlessly.

...and so on for every row of data we have. To a sighted user, it may seem a drag that every piece of data is proceeded by its header. To a blind or vision impaired user it can be the only way to keep track of a relationships in a complex set of data. If your headers are made up of quite long information, this can be quite a nuisance, but there is also a way to deal with this. Your headers can also take on an abbr attribute where you type in an abbreviated reference to your header title. here is an example using our table's headers:

<tr>
  <th id="h1">Time.</th>
  <th id="h2" abbr="planned">Planned Task</th>
  <th id="h3" abbr="preferred">Preferred Task.</th>
  <th id="h4" abbr="actual">What I actually did.</th>
</tr>

The cool thing about this is that on its first pass, the reader will render the full header, then for every subsequent row of data it will only read out the abbreviated value for the header. This gives the user a reference point without having to listen to the full header at every cell.

Digging Deeper

Before I close up here,I will mention that HTML4.0 also introduced an axis attribute which is still to gain support amongst many assistive technologies. The axis attribute is to help explain more complex informational structures and if you want to take a look into it you will see that it is well outside the scope of this article.On close inspection the axis attribute also looks suitable for more complex data mining as well as accessibility - once the technology is in place. For more information about the axis attribute read the w3 recommendations for tables. In the meantime I hope you find these simple techniques for making your tables accessible of use and start implementing them into your own sites.

Tim Roberts runs a personal site devoted to accessible web design and other day to day issues called WiseGuysOnly.

He is originally from the rainy North of England, but now lives under the Sunshine of Spain's Costa del Sol. In his spare time he works as Senior Developer for Reliant Webs, looks at the stars and watches lots of videos.

Wow

Submitted by Fingland on September 30, 2002 - 14:40.

Thanks for the extremely informative article, I had thought I knew how to use tables... little did I realize how wrong I was, though I suspect that on a data intensive site this could bulk things up a bit, for sites where tables are rare or for sites with a broad audience (i.e. a city of ... site) this would be a great way to make the site more universally friendly.

login or register to post comments

A couple of suggestions

Submitted by dorward on September 30, 2002 - 23:32.

I would have been nice to see the use of <thead> and <tbody> etc along with example code for the finished table so everything could been seen in context. Very nice article though.

login or register to post comments

Great

Submitted by JohnColby on October 1, 2002 - 10:21.

This is one of the most straightforward articles I've seen on this subject - I'll be using it to present the method to our developers - thanks. And the techniques look to be entirely forward compatible.

login or register to post comments

Associating headers with cells

Submitted by kirkaracha on October 1, 2002 - 11:16.

You can also use the scope attribute (<th scope="row"> or <th scope="col">) to associate the headers with the data cells.

login or register to post comments

That sounds like a fine idea

Submitted by ghurtado on October 2, 2002 - 16:18.

But why dont aural browser makers incorporate some of this functionality at their level? what i mean is, if the browser knows that its parsing a table, couldnt it just as well read every heading before every cell? I dunno, it may just help for a lot of old code that will not get rewritten this way.

login or register to post comments

Accessibility first

Submitted by LintHuman on October 3, 2002 - 01:52.

I’m an advocate of web accessibility so it was good to see some positive stuff on evolt about this, thanks Tim. HTML tables and forms are probably the two most commonly used parts of web pages that cause difficulties for people with disabilities because they’ve not been marked up using all the attributes and elements available.

There are several HTML elements that many designers simply haven’t heard of that can improve the delivery of content to users. For example, how many of us are using these everyday?

  • <abbr>
  • <acronym>
  • <cite>
  • <code>
  • <fieldset>
  • <legend>
  • <optgroup>
  • <q>
  • <tfoot>
  • <thead>

I know support for some of these elements (particularly <abbr> and <q>) is either non-existent or problematic in the major browsers, but all of them can add extra meaning to content, providing semantic context that is understood by assistive technologies.

Hmmn, I feel an article coming on…

login or register to post comments

And another thing

Submitted by LintHuman on October 3, 2002 - 02:01.

Oh, and you can also use the headers and axis attributes in the &lt;th&gt; tag.

The W3C has some useful information on associating header information with data cells.

login or register to post comments

Ignore the above

Submitted by LintHuman on October 3, 2002 - 02:16.

Oops! Just ignore that last comment, please — either too little coffee or too much… Gah.

login or register to post comments

Do th id's need to be unique?

Submitted by boysimple on October 3, 2002 - 20:43.

Say I have 2 tables on a page - do the th id's for each table need to be different? Or can I use, for example, id="hi" over and over again?

as an aside - thank you muchly for diveintoaccesability - it was very reaffirming.

E

login or register to post comments

I prefer SCOPE to HEADERS="id"

Submitted by bearwalk on October 4, 2002 - 04:02.

I think IDs always have to be unique for the page.

Here's an example of using scope instead of headers:

<table>
<thead>
<tr>
<th scope="col">Time</th>
<th scope="col">Planned task</th>
<th scope="col">Preferred task</th>
<th scope="col">What I actually did</th>
</tr>
</thead>
<tbody>
<tr>
<td scope="row">10-12</td>
<td>Catch up on replying to my emails.</td>
<td>Have a lie in.</td>
<td>Surfed aimlessly.</td>
</tr>
<tr>
<td scope="row">12-1</td>
<td>Have Lunch.</td>
<td>Have Lunch.</td>
<td>Had Breakfast.</td>
</tr>
<tr>
<td scope="row">1-5</td>
<td>Finish that project.</td>
<td>Go to video store.</td>
<td>Caught up on my emails.</td>
</tr>
</tbody>
</table>

Notice that I also added scope=&quot;row&quot; to the first column's &lt;td&gt;'s, because that cell describes the row.

IBM Home Page Reader (which is usually referred to as an aural browser, although it doesn't support aural CSS) can read this info very nicely if you switch to "table reading mode". It also respects the abbr attribute of &lt;th&gt;.

login or register to post comments

No difference.

Submitted by wiseguysonly on October 4, 2002 - 05:23.

Hi, thanks to everyone for their great comments:

As far as using scope vs headers goes on simple tables, there really is no diiference in the final outcome. I have always used headers / id, so it is just a habit. A good habit, whichever method you choose.

Scope does have the benefit of being easier to remember, as it remains the same attribute in both headers and cells, but it can only be employed in simple layouts like I have illustrated above. For more complex tables you should look into using the axis and id attributes together.

login or register to post comments

Author for the future

Submitted by bertilow on October 4, 2002 - 05:53.

Good article. There are probably few aural browsers around today that actually use this extra information, but that should not stop us from adding it. Most of the time we author pages that will stay on the web for a long time - or at least they should be capable of staying. Some day aural browsers will catch up, and then forward-looking pages will automatically improve, even though the author might not be around any more to see his pages working even better than they did when he made them.

login or register to post comments

More tags

Submitted by nlfan on October 4, 2002 - 17:08.

LintH left off a few more that I didn't know about until recently. Some don't make some books (for example, &lt;dfn&gt; is not in the O'Reilly HTML Pocket Reference but is in the older DHTML "flamingo" book by Danny Goodman).
&lt;address&gt;
ownership
&lt;code&gt;
intead of &lt;pre&gt; when displaying source
&lt;dfn&gt;
defining instance of new words
&lt;del&gt; &amp; &lt;ins&gt;
delete & insert markup changes corrections
&lt;dl&gt; / &lt;dt&gt; / &lt;dd&gt;
descriptive lists (such as list of tags)
&lt;kbd&gt;
entering characters on a keyboard
&lt;label&gt;
form labels
&lt;samp&gt;
sample output
&lt;var&gt;
variable
Several of these are oriented for software programs, but all could make for better document structures. Many are supported in IE6 (and earlier) and Mozilla. Maybe others can say if there's any support in HPR or other accessibility tools (like JFW).

login or register to post comments

What's the point of using &lt;strong&gt;?

Submitted by moonbiter on October 24, 2002 - 12:16.

Nice article, but a nitpick: Why are you using the &lt;strong&gt; element in the table headers? The table headers already have a different structural meaning than table cells, so there's no real point. If you are using the &lt;strong&gt; to get a bold effect, why not simply use CSS? Something like:

th {
    font-weight: bold;
    stress: 50;
}

login or register to post comments

re: What's the point of using ?

Submitted by glaven on November 1, 2002 - 18:29.

i really don't know the answer to this, but one idea i had was that maybe the <strong> tag is more well supported in aural browsers than css is.

i don't know, just an idea.


chris.

login or register to post comments

Here's a tool that you may all find very useful

Submitted by lloydi on November 19, 2002 - 05:54.

The Accessible Table Builder It will go through a series of steps asking what properties you want the table to have and then generates the mark-up for you, complete with the accessibility features. Well worth bookmarking

login or register to post comments

Relating headings to groups of columns

Submitted by mcombs on April 2, 2003 - 07:58.

I'm unclear on the best (most accessible) HTML for a table that has groups of columns, like I've shown. I want to use the scope attribute, or something similar, to show the relationship between the heading, subheading, and the data in a column.

Loss for Top 10 Customers
Name Inbound Loss Outbound Loss
Avg Min Max Avg Min Max
192.168.127.2_IF: 23 (100Mbps) 0.76 0.00 3.42 0.76 0.00 3.42
192.168.127.2_IF: 23 (100Mbps) 0.76 0.00 3.42 0.76 0.00 3.42
192.168.127.2_IF: 23 (100Mbps) 0.76 0.00 3.42 0.76 0.00 3.42

It seems to me that I need to apply a scope="the next 3 cols" to the heading cell inbound loss, but of course, there is no such property value. What's the best way to call out this relationship?

login or register to post comments

Re: Relating headings to groups of columns

Submitted by bmason on April 6, 2003 - 10:50.

That would be done with the colgroup tag, as in:

Loss for Top 10 Customers
Name Inbound Loss Outbound Loss
Avg Min Max Avg Min Max
192.168.127.2_IF: 23 (100Mbps) 0.76 0.00 3.42 0.76 0.00 3.42
192.168.127.2_IF: 23 (100Mbps) 0.76 0.00 3.42 0.76 0.00 3.42
192.168.127.2_IF: 23 (100Mbps) 0.76 0.00 3.42 0.76 0.00 3.42

login or register to post comments

Re: Relating headings to groups of columns

Submitted by bmason on April 6, 2003 - 11:13.

Oops, looks like some of the code got stripped out when my comment posted. You can view the code here.

login or register to post comments

Thanks!

Submitted by mcombs on April 6, 2003 - 20:20.

Thanks -- I'd read the docs on colgroup, but just didn't get it. Your example was right on the mark.

login or register to post comments

Which browsers support these technologies?

Submitted by branko on May 2, 2004 - 06:54.

I am having a real problem with claims that browsers for the blind could make a mess of things, especially when those claims are used to introduce 'assistive technologies' that either authors or lazy browser manufacturers should support.

However, I am not sure that this is the case here, so perhaps somebody could enlighten me.

It would seem to me that if you have a table with heading cells and data cells, it would be fairly trivial for a browser to associate the heading cells with the data cells. None of the examples here seem to make sense. In which instances do you need to associate certain headings with certain data cells? Which browsers for the blind support the several assistive technologies that W3C's HTML offers?

The sort of table that springs to mind:

heading 1heading 2heading 3
data 1,1data 2,1data 3,1
data 1,2data 2,2data 3,2
data 1,3data 2,3data 3,3
heading 4heading 5heading 6
data 4,1data 5,1data 6,1
data 4,2data 5,2data 6,2
data 4,3data 5,3data 6,3

But even here I can see how a browser could fairly easily guess the associations.

login or register to post comments

No guessing

Submitted by bmason on May 2, 2004 - 08:05.

With the right markup, any technology that does support this HTML shouldn't have to guess. I would have suggested something like this for your table:

heading 1 heading 2 heading 3
data 1,1 data 2,1 data 3,1
data 1,2 data 2,2 data 3,2
data 1,3 data 2,3 data 3,3
heading 4 heading 5 heading 6
data 4,1 data 5,1 data 6,1
data 4,2 data 5,2 data 6,2
data 4,3 data 5,3 data 6,3

login or register to post comments

'Guess' is not a swear word

Submitted by branko on May 2, 2004 - 08:32.

All browsers must use heuristics. There is no magical, absolute connection between document structure and document display. Guessing is not an ugly word here.

Your solution seems to encapsulate the example I gave nicely in accessible HTML. I would still like to argue, though, that I don't understand how a browser could interpret that and other tables any other way.

login or register to post comments

Vector Matrix

Submitted by nainil on May 2, 2004 - 20:14.

Does the building accessible tables help in fetching data using Java's Vector Matrix? I feel that the examples seen above definately strike to the point that usability can be shown and expressed through Building blocks

login or register to post comments

very nice article. There are

Submitted by Ad3m on May 16, 2009 - 19:03.

very nice article. There are probably few aural browsers around today that actually use this extra information, but that should not stop us from adding it. Most of the time we author pages that will stay on the web for a long time - or at least they should be capable of staying. Some day aural browsers will catch up, and then forward-looking pages will automatically improve, even though the author might not be around any more to see his pages working even better than they did when he made them.

login or register to post comments

The access keys for this page are: ALT (Control on a Mac) plus:

evolt.orgEvolt.org is an all-volunteer resource for web developers made up of a discussion list, a browser archive, and member-submitted articles. This article is the property of its author, please do not redistribute or use elsewhere without checking with the author.