Using Tables for Layout: How to Build a Bulletproof* Table Using Transparent Pixel Shims

*Disclaimer: Note that nothing is 100% "bulletproof" when it comes to Web browsers and HTML.

This technique of using invisible tables for Web page layout, while still widely used, is no longer considered to be the best coding practice. Browser support of cascading style sheets has improved; now using CSS is considered to be the preferred method of page layout. But if you really need to use tables for layout, or understand the technique, read on. (By the way, using tables for layout is still the preferred method of styling HTML email. The most widely used email clients are a generation or two behind Web browsers in their CSS positioning support. So if you need to code a pretty email piece, this is the technique for you.)

This example demonstrates the technique commonly used to force Web browsers to consistently render HTML tables. This trick (sometimes called a "hack" or "kludge") keeps tables from collapsing, regardless of the contents of the table. Here we will use use pixel shims to fix the width of the table data cells, and thus of the whole table. Of course, you need to understand basic HTML table construction to use this tutorial.

This example is an oversimplification of the technique, made simple for demonstration purposes. For example, here we use a three-column layout. But normally for a three-column layout you would actually make five columns: three main columns, and two narrow gutter columns, one each between the main columns, to create space between the main columns (because cellpadding — the space within cells — and cellspacing — the space between cells — must be set to zero).

You will need a transparent pixel GIF. If you don't already have one, you can download a transparent pixel here.

Step 1 - With paper and pencil, sketch out a mock-up of the page layout.

table layout sketch

Step 2 - Add a row at the very top of the table sketch.

When all is said and done, this row will be only one pixel tall, and will be invisible.

table layout sketch

Step 3 - Define the columns.

Use vertical lines to define all possible columns, even if a line cuts through a row (as these lines cut through the row containing the headline).

table layout sketch

Step 4 - Define the rows.

Use horizontal lines to define all possible rows, even if a line cuts through a column (as a line cuts through the text block on the left).

table layout sketch

Step 5 - Define the column widths.

First decide how wide the entire table is to be. (In this example we will set the table width at 600 pixels, a size that is fairly narrow.) Then decide on all column widths, which of course when added up must equal the table width, excactly. Remember that each column must be at least as wide as any images that will be placed into a cell in that column.

table layout sketch

Step 6 - Refine the table structure.

Note that each column in the top row will become a cell containing an invisible pixel. Now erase the lines that cut through cells.

table layout sketch

Step 7 - Code the table.

Now we can clearly see the underlying table structure.

table layout sketch

Note that this table is four rows by three columns, and that the first row, reserved for the invisible pixels, will become only one pixel tall. Also note that the table data cells in this top row will not contain any rowspan or colspan attributes.

The width of the table data cells is set by using the width attribute of the invisible pixel <img> tags, not by using the width attribute of the <td> tags. The cellspacing, and cellpadding attributes of the <table> must be set to zero, and the width attribute of the <table> must be set to some fixed number, such as 600, 800, 1000, or whatever. The border must be set to zero; in the code below, a local style is used to do this.

Here is the code for the above table:

<table style="border:0;" cellspacing="0" cellpadding="0" width="600">
<tr>
<td><img src="images/cleardot.gif" width="175" height="1" alt="" /></td>
<td><img src="images/cleardot.gif" width="300" height="1" alt="" /></td>
<td><img src="images/cleardot.gif" width="125" height="1" alt="" /></td>
</tr>
<tr>
<td colspan="3">CONTENT</td>
</tr>
<tr>
<td rowspan="2">CONTENT</td>
<td rowspan="2">CONTENT</td>
<td>CONTENT</td>
</tr>
<tr>
<td>CONTENT</td>
</tr>
</table>

The above code validates to XHTML 1.0 Strict.

Note that in this example the width of the table is fixed, not its height. You are usually much more concerned with the width than the height. To fix the height instead of the width, you can use this technique, but with an added column for pixel shims (with a width equal to one pixel) instead of an added row. If you wish to fix both the table's width and height (not recommended) you will need to be very careful to allow enough room for text in the cells to get larger without breaking the table structure.

Also note that for invisible pixels used as spacers or shims, the empty alt value (nothing between the quotes, as in <img alt="" src="cleardot.gif" /> ) is used. This stops screen readers for the visually impaired from reading aloud meaningless alt text.

The CSS

Of course, it's better to put all styling in the CSS rather than in the HTML. In the above sample code for the table, the HTML attributes of the <table> element (width, cellpadding, and cellspacing) are used, as well as a local style to remove the border. But it's cleaner to put all of this into the style sheet. Here's sample HTML code to do this:

<table class="layouttable">
<tr class="shimrow">

<td><img src="images/cleardot.gif" width="175" height="1" alt="" /></td>
<td><img src="images/cleardot.gif" width="300" height="1" alt="" /></td>
<td><img src="images/cleardot.gif" width="125" height="1" alt="" /></td>
</tr>

</table>

Note that the table used for layout has a class applied to it called "layouttable" and the first row (the row containing the pixel shims) has a class applied to it called "shimrow."

Here's the CSS:

.layouttable {
width: 600px;
}
.layouttable, .layouttable td, .layouttable th {
border-style: none;
padding: 0;
margin: 0;
}
.shimrow td {
font-size: 0;
line-height: 0;
}

Note that the cells in the row contining the shims have the line-height property set to zero. This stops these cells from growing taller than one pixel in height.

Tip: While building and modifying an invisible table to be used for page layout, it is very helpful to actually see the cell borders. To do this, add this rule to your CSS:

td {
border-style: solid !important;
border-width: 1px !important;
}

Of course, while you are making the cell borders visible by making them one pixel wide, you are adding a few extra pixels to the width of the table, which will cause things to be slightly off. But this allows you to easily see the table structure. Then, when you have finished the layout and you no longer need to see the actual cell structure, remove the above CSS code to make the table invisible.