Scalable 3-Column Layout using a <table>

Objective We want a column on the left and a column on the right with widths specified in 'em' units*. We also want a page header at the top of the page and a footer at the bottom of the page. The footer should be positioned at the bottom of the viewport/screen when the page is shorter than the screen.

Outline of Method

We cannot use the width attribute of the <td> tag to specify a width in 'em' units because the HTML 4.01 Specification allows the width to be specified only as an integer number of pixels or as a percentage of the actual table width. Instead we will use a style to apply a width specified in 'em' units to the column.

We also want the table to stretch vertically to the full height of the browser window. We might be tempted to insert a property 'height="100%"' on the <table> tag. But, the <table> tag does not have a 'height' attribute. Although some browsers do interpret a height attribute on a table this behaviour is non-standard. We will use a style specification to give it a height so that our solution can comply with W3C standards.

* We are using 'em' units so the page can be used with menus that are dimensioned in 'em' units. Such menus expand/contract proportionately when the user changes the default fontsize in the browser.
Note Menukit can build CSS Menus using 'em' units.
  1. Create a local site for this tutorial. Download the support files for this tutorial. Create an empty site and copy the support files into it. Start Dreamweaver and open the start page, 3colTableEms_start.htm.
  2. Analysis of the 3colTableEms_start.htm page. The start page contains a 3 X 3 table. The table has a temporary 1-pixel border so we can see what is happening as we apply style settings. The cellpadding and cellspacing are both 0.

    We labelled the table "wrapper" and applied a style to set the height to 100% and the width to 99.8% (see comment box below).

    Annotated source code.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <title>3 Column Layout (using a table)</title>
    <style type="text/css">
    Browsers make the body element only as tall as is needed for the actual page contents - they do not stretch the height to fill the browser window (or more correctly, the viewport). But we can force the <body> to stretch to 100% of the viewport by giving it a height of 100% with a style specification. In some browsers, the <body> element gets its height from the <html> element rather than directly from the viewport. To cater for these browsers we also give the <html> element a height of 100%.
    html {
    height: 100%;
    }
    body {
    margin: 0;
    padding: 0;
    background: #FBFBFF;
    color: #000033;
    height: 100%;
    }
    Why a width of 99.8%? If the column widths are specifed in 'em' units, Firefox sometimes displays unnecessary scrollbars when the viewport is made narrow. (Possibly an arithmetic rounding error when Firefox converts from ems to pxs?) The scrollbars can be eliminated by making the width slightly less than 100%.

    Note. As the % is reduced, a margin appears on the right of the wrapper that allows the body background color to show through.

    #wrapper {
    height: 100%;
    width: 99.8%;
    }
    </style>
    </head>
    <body>
    <table id="wrapper" width="100%" border="1" cellspacing="0" cellpadding="0">
    <tr>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    </tr>
    <tr>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    </tr>
    <tr>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    </tr>
    </table>
    </body>
    </html>
    3colTableEms_start.htm
  3. Create a header. To create a header we merge the 3 cells in the first row. Give the header a height of 6em, a background color of #000059 and a text color of #F2F2FF.

    Modify the first row in the table to look like this:

    Delete the second and third cells and make the first cell stretch across the full width of the table.
    <tr>
    <td id="header" colspan="3">&nbsp;</td>
    </tr>

    Include a style for it in the page's head section like this:

    #header {
    height: 6em;
    background-color: #000059;
    color: #F2F2FF;
    }
  4. Create a footer. To create the footer we merge the 3 cells in the third row. Give the footer a height of 4em, a background color of #80A7E0 and a text color of #000033.

    Modify the third row in the table to look like this:

    <tr>
    <td id="footer" colspan="3">&nbsp;</td>
    </tr>

    Include a style for it in the page's head section like this:

    #footer {
    height: 4em;
    background: #80A7E0;
    color: #000033;
    }
  5. Create a left column.We want a navigation column on the left with a width of 7.5em so that a CSS Flyout menu with a width of 7.5em fits snugly into it. Specify a style for the first cell in the middle row like this:

    The preset themes that come with Menukit generally have a width of 7.5em. You can use these themes if you want to or you can make your own themes using whatever sizes, colors, etc you want.
    #left {
    width: 7.5em;
    }

    and modify the table definition like this:

    <tr>
    <td id="left">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    </tr>
  6. Create a column on the right.You can give this whatever width you want (we made it 10ems wide) or you can delete it if you just want a 2-column layout. Specify a style for the third cell in the middle row like this:

    If you decide to delete this cell from the table then change the colspans in the header and footer to 2.
    #right {
    width: 10em;
    }

    and modify the table definition like this:

    <tr>
    <td id="left"></td>
    <td></td>

    <td id="right"></td>
    </tr>
  7. Style the main content area. The central cell acts as a container for the main page contents. Here we will set a text color and a background color for the cell. We will also set a 1-pixel border along the left and right sides to make the side columns stand out. First set the cell's identifier to 'content'...

    <tr>
    <td id="left">&nbsp;</td>

    <td id="content">&nbsp;</td>
    <td id="right">&nbsp;</td>
    </tr>

    ...and create a style for it like this:

    Now we can remove the temporary border that we applied to the table by setting the attribute border="0" on the <table> tag.
    #content {
    background: #FBFBFF;
    color: #000033;
    border-left: 1px solid #000055;
    border-right: 1px solid #000055;
    }

    We have set the colors for the header, footer and main contents area. However we have not defined any colors for the sidebars. We'll take care of that in the next step.
  8. Set the colors of the side columns. It would be easy to assign a different pair of text and background colors to the left and right sidebars by adding the required colors into the #left and #right styles that we created in steps 4 and 5 above. Here we are just going to use the same combination of text and background colors for each side so we can set the colors for the table itself in the #wrapper style.

    #wrapper {
    height: 100%;
    width: 99.8%;

    background: #DDEEFF;
    color: #000033;
    }
  9. Vertical Alignment. At the moment, if we were to just 'pour in' content into the side columns or main area we would find that the contents would be aligned vertically in the middle of each area (the default for table cells). We can change that by adding another style that resets the default vertical alignment for all table cells like this:

    #wrapper td {
    vertical-align: top;
    }

    See the finished 3-column page with some filler text added in 3colTableEms_final.htm which you can find in the support files.

    Now you can replace the temporary filler text by a space character to make an empty 3-column layout, 3colTableEms.htm, ready to receive content.

Review We created a 3-column layout using a table that fills the browser window. We used style elements to give the first row a height of 6em and the bottom row a height of 4ems. We did not set any height on the middle row. Instead, we made the table stretch to the full height of the browser window because we want the remaining space (after the header and footer) to be allocated to the middle row of the table.

A problem with Internet Explorer If you view the page with IE you will notice that the heights of the header and footer expand when the browser's lower edge is dragged downwards. IE does not allocate the remaining space to the middle row. It distributes it among all the rows, in effect interpreting the 'height' specification as 'minimum height'.

This problem is only noticeable with pages that are significantly shorter than the browser height.

We provided a JavaScript solution to a similar problem in a previous tutorial where the heights of the header and footer were specified as attributes of the table cells. That JavaScript solution will not work in this case because the heights are specified here in style elements. Therefore you will have to use pixel-based heights if you want to use that solution here.

Of course, switching to pixel-based heights will not affect the variable em-based widths of the side columns.

Supplement Narrowing and centering the table-based layout is straightforward.
  1. Reduce page width and Center it

    First we set the page background to the dark color that we want for the margins and reduce the width of the table, like this:

    body {
    margin: 0;
    padding: 0;

    background: #999999;
    color: #000033;
    height: 100%;
    }
    #wrapper {
    height: 100%;

    width: 95%;
    background: #DDEEFF;
    color: #000033;
    }

    Then we align the table in the center like this:

    <body>
    <table border="0"
    align="center" cellpadding="0" cellspacing="0" id="wrapper">
    <tr>

    Your page should now look like page 3colTableEms_centered.htm which you can find in the support files.