Make sure you don't miss the latest insights and tips. Click here to sign up for my mailing list now! »

HTML Tables – when and how to use tables in HTML

[include filepath=”/sm-includes/inc/books/semantic-html.php”] [include filepath=”/sm-includes/inc/books/production1.php”]

Example HTML Table

Column 1 Column 2
Example of a simple table The table has 2 columns, each one with a column header (above).
The first 2 rows each have 2 cells One cell in each column.
Whereas this 3rd row has a single cell spanning 2 columns.

Correct Semantic use of Tables in HTML

HTML tables should only be used for rendering data that belongs naturally in a grid, in other words where the data describe a number of objects that have the same properties.

This data may be enterable by the user in a form, as long as each column and row contains similar content.

HTML Table Example

Order# Item Number Total price
145 1700mm Corner luxury bath 2 £990.00
146 Duoflow System 1000 1 £1,999.00
147 Ideal Standard Space Offset Corner Shower Bath 2 £2,200.00
151 Wilux Bebop 1 £849.95

Tables should not be used for layout

For several years, web designers used tables as the only way to structure web pages, but CSS now makes their use redundant.

It is true that there remain a few things that are easier to do using tables.
The main benefit of tables is that all cells in a row, and all cells in a column, stretch together as the row or column stretches.
This effect is sometimes achievable in CSS, sometimes achievable with difficulty, and sometimes impossible.

However, don’t use tables for layout because:

  1. It is semantically incorrect, and
  2. Tables are less flexible than divs etc.

e.g. It is possible to rearrange the order in which boxes are displayed on a page, even make them stack, just by changing a few CSS properties.
This is impossible with tables, which are rigid and immovable.

How to do tables

We’ll go through how to construct tables in HTML, including a few useful tricks.

The basic elements of tables are:

<table> </table>
The start and end of the table.
<thead> </thead>
The start and end of the table head section, which includes column headers
<th> </th>
A table heading cell, which is a column header or row header
<tbody> </tbody>
The start and end of the main body of the table, which contains the actual data
<tr> </tr>
Table row; used in both the table head and table body
<td> </td>
Table cell (stands for "table data"), which holds the actual data

Example table HTML

<table>
  <thead>
    <tr>
      <th>Column 1</th>
      <th>Column 2</th>
    </tr>
  </thead>
  <tbody>
  <tr>
    <td>Example of a simple table</td>
    <td>The table has 2 columns, each one with a column header.</td>
  </tr>
  <tr>
    <td>The first 2 rows each have 2 cells</td>
    <td>One cell in each column.</td>
  </tr>
  </tbody>
</table>

Walk-through the table code

<table>

This tells us a table is starting.

In normal HTML, there are a few parameters you can use.
However, these are not permitted in xHTML.

border="n"
Border thickness, applied to every cell. If you use xHTML (and also to follow best practice), you’ll need to apply the CSS border property to the td and th elements.
cellpadding="n"
Padding (spacing) inside every cell. Alternatively, use the CSS padding property.
cellspacing="n"
Spacing outside every cell, separating them from each other. In CSS, use the margin property.

<thead>

The table head section does not contain actual data, just header cells for columns (<th> tags).

If you want column header cells, these should go inside a <thead>, not in a table row (<tr>).

<tr>

The first table row in the table head section indicates a row of header cells.

<th>

These table head cells appear both in the table head section (<thead>) and in table rows (<tr>.

In the table heading section, they are column headers; in table rows, they are effectively row headers.

The content between the start and end tags will appear in the header cell.

<tbody>

After the <thead> has been closed, put the main body which will contain your rows of data.

You don’t have to use a <tbody> section, but you should if you use a <thead> section with column headers.

<tr>

Each row in the table body has to be defined with start and end table row tags.

<td>

Start and end tags define an actual table data cell.

Table tricks

Here are a few useful techniques you’ll need when creating HTML tables.

  • Making cells span across columns or rows.
  • Setting properties of columns and groups of columns.

Making cells span across columns or rows

You can use the properties colspan and rowspan for a <td> to make that cell span across more than one column or row.

The trick is making sure you remove the relevant cells in adjacent rows or columns, which are being merged.
Trial and error is the only way to get these right.

Example of colspan and rowspan

colspan="2", rowspan="2" colspan="2"
  rowspan="2"
     

Code for example above

<table>
  <tr>
    <td colspan="2" rowspan="2">colspan="2", rowspan="2"</td>
    <td colspan="2">colspan="2"</td>
  </tr>
  <tr>
    <td> </td>
    <td rowspan="2">rowspan="2"</td>
  </tr>
  <tr>
    <td> </td>
    <td> </td>
    <td> </td>
  </tr>
</table>

Setting properties of columns and groups of columns

You can define certain properties for whole columns at the top of your table (between the <table> and <thead> tags), using the <col /> or <colgroup /> tags.

<col /> is for setting the properties of one column at a time.
<colgroup /> is for setting properties for several columns together.

(Note that both tags are self-closing, so if you’re using xHTML, you must use the trailing forward-slash.)

Where I find these tags most useful is for setting the widths of columns (without having to set widths for particular cells).
What’s great about it is that you can use the same settings for a series of tables, and be sure that relevant columns will line up, even if the amount of content in cells varies.

(If you don’t set widths for columns, then your browser should squish the columns of a table around in order to minimise the table’s overall length.)

Example

Table 1

Col 1 Col 2 Col 3
Some content in this table, not lots, but it varies.
This row has significantly more words in it Although not every cell does, like the following cell is empty.  

Table 2

Col 1 Col 2 Col 3
You’ll notice that this table has more content in the third column than the previous one did.
Yet its columns remain the same widths as the one above. This is great when laying out series of tables containing similar data, but which you want to separate with other content like headings.

Code for above example

<p><strong>Table 1</strong></p>

<table style="90%;">

<col style="width:15%;" />
<col style="width:55%;" />
<col style="width:30%;" />
<thead>

<tr>

<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>

</tr>

</thead>
<tbody>
<tr>

<td>Some content</td>
<td>in this table, not lots, but</td>
<td>it varies.</td>

</tr>
<tr>

<td>This row has significantly more words in it</td>
<td>Although not every cell does, like the following cell is empty.</td>
<td> </td>

</tr>
</tbody>

</table>

<br />

<p><strong>Table 2</strong></p>

<table style="90%;">

<col style="width:15%;" />
<col style="width:55%;" />
<col style="width:30%;" />
<thead>

<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>

</thead>
<tbody>
<tr>

<td>You’ll notice</td>
<td>that this table</td>
<td>has more content in the third column than the previous one did.</td>

</tr>
<tr>

<td>Yet</td>
<td>its columns remain the same widths</td>
<td>as the one above. This is great when laying out series of tables containing similar data, but which you want to separate with other content like headings.</td>

</tr>
</tbody>

</table>

A more flexible way to do the above would be to use CSS, assigning classnames to the different columns, e.g.

<td class="col1of3"> Content here </td>
<td class="col2of3"> Content here </td>
<td class="col3of3"> Content here </td>

You could then set all the column-widths centrally in your stylesheet, and they would apply to every table.

<colgroup />

Use column groups for setting the properties of numerous consecutive rows, using the span property, as follows.
(You can mix up single cols and colgroups.)

  <col style="width:20%;" />
  <colgroup span="3" style="width:15%;" />
  <col style="width:35%;" />

The example above would apply to a table with 5 rows.

  • The first row would be 20% of the width of the table.
  • The next 3 rows would be 15% each.
  • The last 5th row would be 35% width.

What other properties can you set using <col /> or <colgroup />?

Not every CSS style property you set in a column definition gets applied to every cell in the column, and other properties will easily override them.

This code…
<col style="

color:#f00;
font-weight:bold;
background-color:#ff6;
border:3px solid #000;

" />

produces this result…

The result will vary according to your browser.
Most browsers will show the background-color.

This text in this cell should be red and bold (not Mozilla).

Its background should be pale yellow (yes) and border thick and black (not Mozilla).
About the author

Ben Hunt

Ben is the creator of Web Design From Scratch. He started writing articles about web design to kill time on a long train commute, and is now one of the most influential figures on the subject of effective web design. He has written three books and spoken at multiple conferences internationally.

Chuck - last year

Hey Ben, You wrote: “HTML tables should only be used for rendering data that belongs naturally in a grid, in other words where the data describe a number of objects that have the same properties. ”

What about a list of users with their last login date, username and some methods to interact with their account (change password, export details, usage report buttons).

It looks good laid out in a table but it could also be laid out as ‘recipe cards’ or as a list.

So that data ‘could’ naturally belong in a grid as well as other formats. Should I use a real HTML table or a series of CSS spans to make it look like it is in a table?

tx.

    Ben Hunt - last year

    Sounds like either a table or a series of divs would be appropriate. It’s hard to say without knowing the full context.

Krishna - last year

I am very sorry for the last two comments,my question is

in the code <col style=”width:20%;text-align:center”> ,

width is working fine, but text-align doen’t have any effect.

Comments are closed