mind your <table> manners
March, 2001.
By Molly E. Holzschlag. (Link to original article.)
Without tables, most Web site designers working across platform and browser types would be unable to create effective layouts, even though current standards recommend against using tables for layout. Unfortunately the suggested alternative—CSS positioning—isn't a realistic option for creating widely interoperable sites. So, despite standards and recommendations, HTML and XHTML authors use tables to lay out their pages, and every visual editor on the market relies on them as a positioning method, too.
But tables can be difficult. In fact, most of the email questions I receive about HTML have to do with problems associated with them. I feel it would be helpful to answer the most common questions and problems here, as well as to provide tips and tricks for producing tables that are streamlined, sensible, and bug-free.
Four ways to make your table layouts better:
- Align your layout vertically, rather than horizontally.
- Avoid gaps in your spliced images.
- Nest and stack.
- Use HTML 4.0 features that make tables more accessible.
Horizontal vs. vertical orientation
So what's the primary secret to streamlining tables? You might be surprised to learn that it has to do with how you spatially design them. Instead of planning from the horizontal layout of a design, study the vertical layout and plan your tables accordingly.
People who read and write in horizontally oriented languages tend to organize visual information horizontally—and while this might be great for the flow of content, it's not necessarily the best way to structure a page. The heart and soul of streamlined table design lies in looking first at the vertical, not the horizontal layout. Rows create the horizontal structures within a table. Cells provide vertical control. In fact, table cells themselves can be considered the core of table layouts for Web design. After all, they control a great deal in terms of structure and display.
Figure 1. Notice the vertical and horizontal structure of this example. The navigation runs vertically, the header horizontally.
Let's say you have a design with navigation set to the left of a page (see Figure 1). The navigation is made up of five graphics. Each graphic is above the next. Many authors' instinct would be to put each of these graphics into an individual row. This is the method that most common visual editing tools use. Listing 1 shows the code as created by Dreamweaver UltraDev. The program approached the page elements from left to right, top line down, and created rows and cells accordingly. As a result, each image is placed in its own row. The resulting code has eight cells and seven rows.
Listing 1. Code as created by Dreamweaver UltraDev.
<table width="585" border="0">
<tr>
<td> </td>
<td><img src="images/whome_header.gif" width="486" height="46"><br></td>
</tr>
<tr>
<td width="100" valign="top"><img src="images/news.gif" width="100" height="25"><br></td>
</tr>
<tr>
<td width="100" valign="top"><img src="images/inside.gif" width="100" height="25"><br></td>
</tr>
<tr>
<td width="100" valign="top"><img src="images/search.gif" width="100" height="25"><br></td>
</tr>
<tr>
<td width="100" valign="top"><img src="images/about.gif" width="100" height="25"><br></td>
</tr>
<tr>
<td width="100" valign="top"><img src="images/home.gif" width="100" height="25"><br></td>
</tr>
<tr>
<td width="100" height="200"> </td>
</tr>
</table>
But if you approach the same design from a vertical orientation, you'll see that there are only two columns. What's more, when you begin to write code based on columns rather than rows, you'll find you need only one row! The resulting code has two cells and one row (see Listing 2). In this vertical design, the cells containing navigation come before the "who me?" header and content areas. I'm reading the structure of the layout from the vertical, not the horizontal, and this has changed the logistical structure of the document. However, the appearance is essentially the same.
Listing 2. Writing code based on columns, rather than rows.
<table border="0" width="585" cellpadding="0" cellspacing="0">
<tr>
<td valign="top" align="left" width="100">
<br>
<br>
<br>
<img src="images/news.gif" width="100" height="25" border="0" alt="news">
<img src="images/inside.gif" width="100" height="25" border="0" alt="inside">
<img src="images/search.gif" width="100" height="25" border="0" alt="search">
<img src="images/about.gif" width="100" height="25" border="0" alt="about">
<img src="images/home.gif" width="100" height="25" border="0" alt="home">
</td>
<td valign="top" align="left" width="486">
<img src="images/whome_header.gif" width="486" height="46" border="0" alt="who me header">
</td>
</tr>
</table>
You can rely on breaks for spacing, or if you want to really fix a position, use spacer GIFs. While some people dislike spacer GIFs intensely, designers who want extremely precise control find them helpful. What's more, there's no reason you can't make a layout partly fixed and partly dynamic. Simply set your table width to "100%" and the content cell to "100%". But keep the navigation cell fixed to the image's size—100 pixels, in this example. This way, the content cell will dynamically fill the available screen space, but the navigation cell will remain fixed.
Closing the gap
Many designers who want to make fixed designs will splice graphics, but as they work with their HTML they find that they can't get the images to properly nestle up against one another. This causes endless frustration as authors attempt a visually smooth and consistent look.
There are several reasons why images won't align properly. The following guidelines will help you avoid gaps in your spliced image designs.
Begin by ensuring that you precisely measure and crop any images, as necessary, for a fixed portion of the design.
In your table tag, include the width in pixels for a completely fixed design. This may be as low as 585 if you're looking to accommodate 640x480 resolution, or higher—depending upon your needs. If only part of your table is to be fixed, you may use a percentage in your width:
<table width="585">
or
<table width="100%">
Include the cellpadding and cellspacing attributes and set each to a value of "0".
<table width="585" cellpadding="0" cellspacing="0">
As I mentioned earlier, a great deal occurs at the table cell level. In your table cell tags, include the precise width of any fixed portion of the layout.
<td width="100">
Also, include a vertical (valign) and horizontal (align) alignment. This adds even more control to how your page is displayed.
<td width="100" valign="top" align="left">
The closing table data tag must appear on the same line as the content it contains. This tag is perhaps the biggest culprit when it comes to gapping problems in table layouts. So:
<td width="100" valign="top" align="left">
<img src="../images/home.gif" width="100" height="25" border="0" alt="return to the home page"></td>
and not
<td width="100" valign="top" align="left">
<img src="../images/home.gif" width="100" height="25" border="0" alt="return to the home page">
</td>
Review any row or column spanning to ensure that you've done it correctly. Improper spanning can cause problems with gapping and rendering in general.
Look closely at your code—have you left out anything? Forgetting to close a cell, row, or the table itself can significantly alter your page, or render it useless.
Nesting instincts
You can achieve a range of design options by nesting and stacking. You can create complex designs, but you'll need to use these techniques with care. I believe that if there's an easier way to do something—do it that way. But if you've tried everything you can think of and can't achieve a particular visual goal, nesting or stacking might be the answer.
Nesting tables is simply placing tables within tables. Because a table cell is a content area that can take text, images, media, and code, you can put a complete table into a cell, and even put a table into a cell within another table. Perhaps you need to control the relationship of an image to text within a content cell. Nesting is a perfect choice to gain control of that object relationship (see Listing 3). Any time you need this level of control, you can consider nesting.
Listing 3. Nesting tables.
<table>
<tr>
<td>
<table>
<tr>
<td>
<table>
<tr>
<td>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
Does nesting slow down rendering? Well, the more code you have, the more code a browser has to interpret, so there's always a bit of a price to pay. What's more, you want to be careful with how deeply you nest. If you've gone more than two levels deep, you're treading the line. The table in Listing 3 does some treading at three levels deep. More than this, and I'd seriously reevaluate your method to see if there isn't a cleaner way to achieve your goal.
Stacking tables is the placement of one table on top of another. It can make certain layouts much easier. Instead of relying on column and row spanning to arrange individual areas and make a more complex table, you might find that creating a separate table for your content is an easier and cleaner way to go. Let's say you've got your main design filling the primary section of your page. But you've got navigation at the bottom (Figure 2). You can put this navigation in a separate table beneath the main table.Figure 2. The navigation at the bottom is in a separate table from the rest of the content.
An advantage to stacking—especially in a navigation scenario like this one—is that you can easily use and manage SSIs (server side includes) or other dynamic, template-based generation for portions of your page. Then, if you decide to change the navigation by adding a new link or graphic, you simply go to the template and change it, and it will be updated site-wide.
All together now
HTML 4.0 introduced several elements to increase accessibility and improve page rendering for tables. Among these elements are captions and grouping options. However, they're compatible with only HTML 4.0-compliant browsers, and you should test for specific compliance or degradation problems in any browser with which you're concerned.
Adding a caption to a table helps clarify its purpose. Do this using the caption element. Typically, an aural device such as a screen reader for the blind reads this caption before it reads the contents of any cell, and the browser renders the caption before the cell's content, too. Listing 4 shows a table with a caption. Try it out and see how it renders in your browser.
Listing 4. Using table captions.
<table>
<caption>Molly's Itinerary</caption>
<tr>
<td>Date</td>
<td>Time</td>
<td>Location</td>
<td>Event</td>
</tr>
</table>
Another accessibility feature, column grouping, is also useful for cleaning up your code by applying structure- or content-related information to grouped columns within your tables.
You can use two elements to control column grouping. I find the colgroup element the most helpful, as it lets you bunch them structurally. The col element lets you group table cell attributes together, but doesn't affect the structure or the interpretation of that structure by browsers, aural devices, or other rendering agents.
In Listing 5, I've created a table with three rows of four cells each. I've grouped the columns together with the colgroup element, and then applied a color to each bunch using the bgcolor attribute in the colgroup tag. So instead of having to put my background color in each of the individual cell tags, I simply applied it using column grouping—a sort of "meta" approach to assigning an attribute to a group. Figure 3 shows how this works.
Listing 5. Column group.
<table border="2" width="100%">
<caption>Column Grouping</caption>
<colgroup bgcolor="green">
<colgroup align="left" bgcolor="pink">
<colgroup align="center" bgcolor="yellow">
<colgroup valign="top" bgcolor="blue">
<tr>
<td>content</td>
<td>content</td>
<td>content</td>
<td>content</td>
</tr>
<tr>
<td>content</td>
<td>content</td>
<td>content</td>
<td>content</td>
</tr>
<tr>
<td>content</td>
<td>content</td>
<td>content</td>
<td>content</td>
</tr>
</table>
Figure 3. Using grouping, I've applied attributes to the column groups rather than the individual cells.
I can also apply attributes to columns using the col element. However, this element only groups the attributes for the columns. You can use the col element the same way you'd use colgroup if all you want to do is apply attributes to columns. However, use the colgroup element for structural interpretation, particularly if designing for aural devices.
An important note: In HTML 4.0, colgroup has an optional closing tag, and col is considered an empty element (closing tag forbidden). So, if you're writing XHTML 1.0 documents, you'll need to accommodate this by always closing your colgroup element, and terminating the col element:
<col width="100%" />
Once your tables are nice and clean, you have my permission to go have some fun.



