Before I jump into the proper way to use tables, I’m going to share an anecdote that should bring a smile to the face of anyone who’s done this stuff for a while.
A few months ago I was both pleased and surprised to discover a web developer who didn’t really know how to lay out a page using tables. He had a sense of how it might work, but had never really done it. I was having him help out with an HTML email (where tables are still the safest bet) and the whole thing was a novelty for him. Looking at it, this makes sense as he’d been at the job for only a few years so he learned entirely in the modern era and he was lucky enough to only learn from good sources. Still, it was a new phenomena for me- encountering a developer who was purely from a CSS-based layout world.
Yes! We’re winning.
If you don’t know what I’m talking about when I talk about tables for layout, move along. There’s nothing to see here.
Anyway, tables.
Tables
Tables are for Tabular Data
Here’s a table full of data.
Total | Player/Opponent | Date | Result/Score |
---|---|---|---|
60 | Larry Bird vs. Atlanta (at New Orleans) | 03/12/85 | W/126-115 |
56 | Kevin McHale vs. Detroit | 03/03/85 | W/138-129 |
53 | Larry Bird vs. Indiana | 03/30/83 | W/142-116 |
51 | Sam Jones at Detroit | 10/29/65 | L/106-108 |
50 | Paul Pierce vs. Cleveland | 2/15/06 | L/109-113** |
50 | Larry Bird vs. Atlanta | 11/10/89 | W/117-106 |
50 | Larry Bird at Dallas | 03/10/86 | L/115-116 |
49 | Antoine Walker at Washington | 01/07/98 | L/108-110 |
49 | Larry Bird vs. Portland | 03/15/92 | ** W/152-148 |
49 | Larry Bird at Phoenix | 02/15/88 | W/107-106 |
And here’s the markup:
<table class="dataTable">
<caption>Boston Celtics Individual Scoring Highs</caption>
<tr>
<th scope="col">Total</th>
<th scope="col">Player/Opponent</th>
<th scope="col">Date</th>
<th scope="col">Result/Score</th>
</tr>
<tr>
<td>60</td>
<td>Larry Bird vs. Atlanta (at New Orleans)</td>
<td>03/12/85</td>
<td>W/126-115</td>
</tr>
<tr>
<td>56</td>
<td>Kevin McHale vs. Detroit</td>
<td>03/03/85</td>
<td>W/138-129</td>
</tr>
<tr>
<td>53</td>
<td>Larry Bird vs. Indiana</td>
<td>03/30/83</td>
<td>W/142-116</td>
</tr>
<tr>
<td>51</td>
<td>Sam Jones at Detroit</td>
<td>10/29/65</td>
<td>L/106-108</td>
</tr>
<tr>
<td>50</td>
<td>Paul Pierce vs. Cleveland</td>
<td>2/15/06</td>
<td>L/109-113**</td>
</tr>
<tr>
<td>50</td>
<td>Larry Bird vs. Atlanta</td>
<td>11/10/89</td>
<td>W/117-106</td>
</tr>
<tr>
<td>50</td>
<td>Larry Bird at Dallas</td>
<td>03/10/86</td>
<td>L/115-116</td>
</tr>
<tr>
<td>49</td>
<td>Antoine Walker at Washington</td>
<td>01/07/98</td>
<td>L/108-110</td>
</tr>
<tr>
<td>49</td>
<td>Larry Bird vs. Portland</td>
<td>03/15/92</td>
<td>** W/152-148</td>
</tr>
<tr>
<td>49</td>
<td>Larry Bird at Phoenix</td>
<td>02/15/88</td>
<td>W/107-106</td>
</tr>
</table>
The important bits are as follows:
- Use headers. The
TH
tags signifiy that those cells are headers. That makes them computer-readable, imparts meaning for screen readers and you can style them. Win-win-win. - Use the
scope
attribute which indicates whether the header is related to the col(lumn) or row. - Use a caption to describe the contents of the table
- It’s not shown, but for complicated tables it’s useful to provide a summary attribute. A summary can describe, in greater detail than the caption, the purpose or structure of the table.
And there you have it, a quick jaunt through the wonderful world of data tables. We’re nearing the end of the tour through the body and then it’s onto CSS and JavaScript. Which will be super fun.