HTML: How to properly mark up a TABLE
These days it's rare to see anyone using HTML elements for tables other than the basic TABLE, TR and TD. This of course makes it much more difficult to apply styles to the table and even more difficult for web spiders and people using screen readers to make sense of the contents.
Proper HTML TABLE Markup
To make an HTML table easier to format and more accessible we can make use of extra tags as shown in the example below:
<table class="t1" summary="Top 10 downloaded movies in 2011 using BitTorrent, in descending order, listing number of downloads and worldwide cinema grosses">
<caption>Most Downloaded Movies on BitTorrent, 2011</caption>
<thead>
<tr>
<th>Rank</th>
<th>Movie</th>
<th>Downloads</th>
<th>Grosses</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="4">torrentfreak.com</th>
</tr>
</tfoot>
<tbody>
<tr><th>1</th><td>Fast Five</td><td>9,260,000</td><td>$626,137,675</td></tr>
<tr><th>2</th><td>The Hangover II</td><td>8,840,000</td><td>$581,464,305</td></tr>
<tr><th>3</th><td>Thor</td><td>8,330,000</td><td>$449,326,618</td></tr>
<tr><th>4</th><td>Source Code</td><td>7,910,000</td><td>$123,278,618</td></tr>
<tr><th>5</th><td>I Am Number Four</td><td>7,670,000</td><td>$144,500,437</td></tr>
<tr><th>6</th><td>Sucker Punch</td><td>7,200,000</td><td>$89,792,502</td></tr>
<tr><th>7</th><td>127 Hours</td><td>6,910,000</td><td>$60,738,797</td></tr>
<tr><th>8</th><td>Rango</td><td>6,480,000</td><td>$245,155,348</td></tr>
<tr><th>9</th><td>The King’s Speech</td><td>6,250,000</td><td>$414,211,549</td></tr>
<tr><th>10</th><td>Harry Potter and the Deathly Hallows Part 2</td><td>6,030,000</td><td> $1,328,111,219</td></tr>
</tbody>
</table>
From the top you will see that there is only one class assigned to the TABLE itself and none to individual rows or cells. All of the formatting is applied based on the class (.t1) using CSS as described below.
The summary attribute of the TABLE is only for screen readers. It gives clues to the user as to what to expect in the table. The caption tag content does appear on the page and can be used to format a heading associated with the table. The caption text can display either above or below the table.
Sections of the TABLE
The contents of the TABLE are divided into three distinct sections - THEAD for the heading, TFOOT for the footer and TBODY for the content (or data). Interestingly we can place the footer content before the table data, but still have it display at the bottom of the table.
This helps not just in applying formatting to the table, but also allows for advanced printing and browsing options for long tables - having the header/footer repeat on each printed page for example, or making the table contents scrollable. More on that later.
The rest of the markup is a combination of TH for the header row and column and TD for the rest.
CSS styles to format the TABLE
Now comes the fun part of applying styles. Most of it is fairly simple and straight-forward, apart from a couple of instances where we use the nth-child pseudo-class to target formatting to specific rows and cells:
<style>
table.t1 {
margin: 1em auto;
border-collapse: collapse;
font-family: Arial, Helvetica, sans-serif;
}
.t1 th, .t1 td {
padding: 4px 8px;
}
.t1 thead th {
background: #4f81bd;
text-transform: lowercase;
text-align: left;
font-size: 15px;
color: #fff;
}
.t1 tr {
border-right: 1px solid #95b3d7;
}
.t1 tbody tr {
border-bottom: 1px solid #95b3d7;
}
.t1 tbody tr:nth-child(odd) {
background: #dbe5f0;
}
.t1 tbody th, .t1 tbody tr:nth-child(even) td {
border-right: 1px solid #95b3d7;
}
.t1 tfoot th {
background: #4f81bd;
text-align: left;
font-weight: normal;
font-size: 10px;
color: #fff;
}
.t1 tr *:nth-child(3), .t1 tr *:nth-child(4) {
text-align: right;
}
</style>
One important step is to set the border-collapse property of the TABLE to collapse. This allows us to apply borders to rows and cells without them doubling up or otherwise looking strange.
The end result
By now you'll be curious how this actually looks in the web browser. With all the formatting applied we end up with the following:
Rank | Movie | Downloads | Grosses |
---|---|---|---|
torrentfreak.com | |||
1 | Fast Five | 9,260,000 | $626,137,675 |
2 | The Hangover II | 8,840,000 | $581,464,305 |
3 | Thor | 8,330,000 | $449,326,618 |
4 | Source Code | 7,910,000 | $123,278,618 |
5 | I Am Number Four | 7,670,000 | $144,500,437 |
6 | Sucker Punch | 7,200,000 | $89,792,502 |
7 | 127 Hours | 6,910,000 | $60,738,797 |
8 | Rango | 6,480,000 | $245,155,348 |
9 | The King’s Speech | 6,250,000 | $414,211,549 |
10 | Harry Potter and the Deathly Hallows Part 2 | 6,030,000 | $1,328,111,219 |
Note that you can now apply this class to any properly marked up data table and the same formatting will be applied. The only data-specific formatting we've used is to right-align columns 3 and 4 and that can be easily removed. Otherwise it doesn't matter how many rows or columns are present.
As a demonstration of this the links below the table (1,2) let you toggle between two different formats. All we are doing is using JavaScript to change the class of the TABLE from .t1 to .t2 and let the CSS rules do the rest.
The rules for the second, orange, formatting are as follows:
<style>
table.t2 {
width: 100%;
border-collapse: collapse;
font-family: Georgia;
}
.t2 caption {
padding-bottom: 0.5em;
font-weight: bold;
font-size: 16px;
}
.t2 th, .t2 td {
padding: 4px 8px;
border: 2px solid #fff;
background: #fbd7b4;
}
.t2 thead th {
padding: 2px 8px;
background: #f69546;
text-align: left;
font-weight: normal;
font-size: 13px;
color: #fff;
}
.t2 tbody tr:nth-child(odd) *:nth-child(even), .t2 tbody tr:nth-child(even) *:nth-child(odd) {
background: #f3eddd;
}
.t2 tfoot th {
padding: 2px 8px;
background: #f69546;
text-align: left;
font-weight: normal;
font-size: 10px;
color: #fff;
}
.t2 tr *:nth-child(3), .t2 tr *:nth-child(4) {
text-align: right;
}
</style>
For anyone using a very old browser, here are some screenshots:
Again, the TABLE markup is identical in each case, only the CSS changes.
alex 4 October, 2017
On Mac OS X 10.13 this code prints header on every page in Chrome, but not in Safari (only on 1st page). The footer is printed only on the last page in chrome and safari. using latest browsers as of 2017-10-04