What's New Tutorial Index References RSS Feed Contact

Tables

Anyone who's seen a data-heavy report, essay, or study knows how useful tables are for quickly and clearly displaying data. They're incredibly useful in web pages as well, good for laying out information, links, and less semantically, images and even entire pages.

HTML provides a whole family of elements for generating and organizing a table's contents. A table's length may daunt you at first, but once you understand the structure, they're remarkably structured and intuitive.

Table terminology

There's a few terms you should know going into working with tables, those being the cell, the row, the head, and the body of the table. Don't worry if the definitions don't mean much to you right now. They will when I start putting together an example table.

Cell

A cell in a table

An individual box in a table is called a cell. There's two kinds of cells in HTML, the standard td, or Table Data, cell, and the th, or Table Header, cell, which gives semantic importance to the cells that define each row and column's meaning.

Row

A row in a table

Cells are nested inside rows. These are made using the tr, or Table Row, element.

The head and body of a table, color-coded

Optionally, you can define a head and body for your table. Rows are nested inside these, allowing you to semantically separate out header rows from data rows. These also provide extra opportunities to style the table using a stylesheet, if you choose. In the graphic, the orange row is the table head, while the blue rows are the table's body.

The table head is defined with the thead element, and the table body is defined with tbody.

Putting together an example table

So before we get ahead of ourselves, let's put together a table piece by piece. Tables, naturally, start with the table element, and then tr elements are nested inside of it. My table will have three rows to start with.

<table>
	<tr></tr>
	<tr></tr>
	<tr></tr>
</table>

This still doesn't display anything, however. You'll need cells inside the table for the table to appear. Let's give each row three cells.

<table>
	<tr>
		<th>Album</th>
		<th>Artist</th>
		<th>Year</th>
	</tr>
	<tr>
		<td>Beautiful Stakes and Powerpoles</td>
		<td>Pine Marten</td>
		<td>2002</td>
	</tr>
	<tr>
		<td>Everyone Down Here</td>
		<td>Earlimart</td>
		<td>2003</td>
	</tr>
</table>
A three-column table
I know, it doesn't look like much.

In order to give your table borders, extra cell spacing, or color, you'll need to use a stylesheet. Good news is that the table's visuals, from the size of the text to the colors of cells to how text is aligned in each of the cells, are fully customizable. If you haven't already tried out CSS, I'll have a link to a page on styling tables in the Further Reading section of this tutorial. Tables, because they're so plain in basic HTML, are a good place to start learning the basics of CSS.

Anyway, to elaborate on table behavior in text: tables have two dimensions, and markup can only go one way, down your page. As a result, each additional tr element adds another row to the bottom of the table, and every td and th nested inside the trs adds another column to the right of the table. If you were to add another td in each row, this table would extend out to four columns automatically.

<table>
	<tr>
		<th>Album</th>
		<th>Artist</th>
		<th>Year</th>
		<th>Length</th>
	</tr>
	<tr>
		<td>Beautiful Stakes and Powerpoles</td>
		<td>Pine Marten</td>
		<td>2002</td>
		<td>49 minutes</td>
	</tr>
	<tr>
		<td>Everyone Down Here</td>
		<td>Earlimart</td>
		<td>2003</td>
		<td>33 minutes</td>
	</tr>
</table>
A three-column table

In case you're wondering, you don't need to segregate out your th and td cells quite like this. You can start off each row with a th, followed by as many td cells as you'd like. There's no rules outside of their semantic meaning.

One last bit of table sugar I'd like to introduce involves the use of captions. Bigger tables can look especially daunting, not just to you as the page author, but to the reader. Adding a caption to your table allows you to summarize the table contents in a single sentence, which will appear above the table on the page. Use the caption element for this. Now, to integrate in a head, body, and caption:

<table>
	<caption>Early 2000s Californian indie rock records</caption>
	<thead>
		<tr>
			<th>Album</th>
			<th>Artist</th>
			<th>Year</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>Beautiful Stakes and Powerpoles</td>
			<td>Pine Marten</td>
			<td>2002</td>
		</tr>
		<tr>
			<td>Everyone Down Here</td>
			<td>Earlimart</td>
			<td>2003</td>
		</tr>
	</tbody>
</table>

Don't mind if there's not much of a visual difference when you add in the thead and tbody. Remember that HTML describes the meaning of content, not how it looks visually. That's the job of a stylesheet.

Here, because we've been looking at very plain tables throughout this section, why don't we look at a styled one quick?

A styled, more visually appealing table
Much better. I wouldn't get into CSS so much here if tables didn't look so flat without it. Here's the example in the image if you'd like to play with it yourself.

colspan, rowspan, and the effects of unequal numbers of cells

One final thing to note in laying out your table are the colspan and rowspan attributes. With these, you can have a cell take up multiple adjacent rows or columns. This is good if you have data that's joined across two categories, or you'd like to give extra headings to separate out sections of the table.

To give you an example I use on my own site, I have a page of best times for courses in Mario Kart Wii. Each course (and successful time trial) gets its own row in the table. As each course in the game is further categorized into cups of four courses, to break up the table, I have one row for each cup name with a single cell that gets stretched across the entire width of the table, taking up all columns for that row.

<table>
	<thead>
		<tr>
			<th>Course Name</th>
			<th>My Time</th>
			<th>Expert Time</th>
			<th>Bike Used</th>
			<th>Date Set</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<th colspan="5">Mushroom Cup</th>
		</tr>
		<tr>
			<td>Luigi Circuit</td>
			<td><strong>01:19.089</strong></td>
			<td>01:19.419</td>
			<td>Bullet Bike</td>
			<td>01/05/20</td>
		</tr>
		<tr>
			<td>Moo Moo Meadows</td>
			<td><strong>01:25.313</strong></td>
			<td>01:25.909</td>
			<td>Bullet Bike</td>
			<td>01/22/20</td>
		</tr>
	</tbody>
</table>
Cells spanning in a table
Note that the "Mushroom Cup" text is perfectly centered in its own row, as its one cell takes up five spaces. Some of the rows below it also feature spanned cells, which appear as empty spaces with the way the table is laid out.

Here's where you can potentially confuse yourself: the total number of columns in the row must still be equal with the other rows. In other words, if you have a cell that spans two columns, that cell now counts as two td elements, and you'll have to remove one of the others. If you don't, one of your cells will stick out of the table, and data will potentially be in the wrong spots in the table. In the case of this table, there's five columns, and a cell spanning two columns, plus four more would make for six places—one too many!

An extra cell sticking out of the table
There are now, in essence, six columns in the table, though most of the rows only have five. Things get squished to accommodate six places, data sits in the wrong column, and no other row fills that sixth column.

If you end up with weird visual errors, just remember to count the number of cells in each row and make sure they equal the same number of columns. A cell spanning three columns counts as three cells.

Summary:

  1. Tables are excellent for organizing data quickly and clearly on a page.
  2. In HTML, tables are represented by nests of elements. Rows (tr) go inside the table, and cells (td for data cells and th for header cells) go inside the rows.
  3. Optionally, tables can also have a head and body, represented by thead and tbody, respectively.
    • Rows nested inside the thead element are semantically treated as header rows, giving meaning to each column, and rows nested inside the tbody element are the data points themselves.
  4. Tables can also have an optional caption element for summarizing the table's contents. This summary will be displayed above the table on the page.
  5. The number of columns in the table is determined by the row with the largest number of cells.
    • This can create visual errors if one row has more cells than the rest of the rows, as most of the rows will appear with blank spaces at the end of them.
  6. You can make a single cell take up multiple rows and columns using the rowspan and colspan attributes.
    • A table cell with a colspan of "3" will take up three columns.
    • If that cell is part of a table with five columns, you'll need to remove two of the other cells in that row. Otherwise, the table will display wrong and data will be in the wrong cells.

Further reading