skip to content

HTML: How to properly mark up a TABLE

 Tweet Share0 Tweets

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"></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 type="text/css"> 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:

Most Downloaded Movies on BitTorrent, 2011
1Fast Five9,260,000$626,137,675
2The Hangover II8,840,000$581,464,305
4Source Code7,910,000$123,278,618
5I Am Number Four7,670,000$144,500,437
6Sucker Punch7,200,000$89,792,502
7127 Hours6,910,000$60,738,797
9The King’s Speech6,250,000$414,211,549
10Harry Potter and the Deathly Hallows Part 26,030,000 $1,328,111,219

class=t1 | class=t2

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 type="text/css"> 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.



Send a message to The Art of Web:

used only for us to reply, and to display your gravatar.

<- copy the digits from the image into this box

press <Esc> or click outside this box to close

User Comments

Post your comment or question

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