Designing Data Part 1: Table structure
The goal of this two-part article is to demonstrate how to create XHTML-compliant tables and how to style them effectively using CSS.
In Part 1, we tackle the basic structure of the table.
Part 1: Table Structure
The first step in any web page development is taking the data and marking it up using semantic and standards compliant XHTML. Let's start with a basic example that you've likely used before.
<table> <tr> <th>Year</th> <th>Quantity</th> </tr> <tr> <td>2003</td> <td>50</td> </tr> <tr> <td>2004</td> <td>100</td> </tr> <tr> <td>Total</td> <td>150</td> </tr> </table>
This is a simple four row table, with the cells in the first row being defined as header cells. Nothing too extraordinary but only the first step in putting our table together.
Next, we add some information about our table and then define our rows a little more.
<table> <caption>Total Sales of Thingamajigs</caption> <thead> <tr> <th>Year</th> <th>Quantity</th> </tr> </thead> <tfoot> <tr> <td>Total</td> <td>150</td> </tr> </tfoot> <tbody> <tr> <td>2003</td> <td>50</td> </tr> <tr> <td>2004</td> <td>100</td> </tr> </tbody> </table>
The caption element on the table helps describe the table and what its purpose is. The caption tag should be the first element after the table tag and is the title of the table. In most browsers, the caption will appear centered and on top of the table. In Part 2, we'll look at ways to change this.
We've also grouped the rows into three elements: THEAD, TFOOT and TBODY. But why is the tfoot BEFORE the tbody? This allows, for example, a user agent (aka: your browser) to display the header and footer of the table while it loads the body of the table in between.
Now that we've described our rows, it's time to describe our columns. There are two elements that accomplish this task: COLGROUP and COL. Let's modify our table again to include this extra information.
<table> <caption>Total Sales of Thingamajigs</caption> <colgroup> <col /> <col /> </colgroup> <thead> <tr> <th>Year</th> <th>Quantity</th> </tr> </thead> <tfoot> <tr> <td>Total</td> <td>150</td> </tr> </tfoot> <tbody> <tr> <td>2003</td> <td>50</td> </tr> <tr> <td>2004</td> <td>100</td> </tr> </tbody> </table>
We've indicated that our table contains one group of columns that has two columns.
Now we tread into troubled waters. Theoretically, most of the attributes that I'm about to get into should be handled using CSS. However, due to browser support or conflicting CSS and HTML support for certain features, I'll proceed to cover them here.
Table Attributes: rules, frame, and border
The border attribute works just as it always has. Just specify a numeric value to indicate how many pixels wide it should be. The border will normally appear bevelled in most browsers unless overridden with CSS.
The frame attribute controls the display of the outer most border on the table. Possible values are void, above, below, hsides, vsides, lhs, rhs, box and border. void is the default value and will remove the border from around the table. Check out the W3C on how these attributes affect the table. How the border is drawn is different in all three browsers that I tested in. IE rendered a 3d border on all sides, Opera a solid black border, and Firefox a gray border on the left and top with black on the right and bottom. In IE, when a value other than void is specified, IE will incorrectly render a border on the cells inside the table as well. For example, if you specify lhs then the left side of each cell will get rendered. Firefox and Opera render this correctly.
The rules attribute has five easy attributes: none, groups, rows, cols, and all. If a value of none is specified then no lines will be drawn in between the cells. This is the default value. Interesting to note here is that if you do not specify a rules attribute, any border style (using CSS) that is set on your colgroup's or col's will not be used. But specify a value of none and suddenly the border style comes to life. A value of groups will apply a border (gray and bevelled in IE, 1px black in Firefox and Opera) around each thead, tfoot, tbody and colgroup. Setting to rows or cols will apply a border between each respectively. All will apply a border around every cell. Again, IE breaks from the pack and displays a border around the entire table when anything but none is specified and the frame attribute hasn't been set.
If you wish to use the frame or rules attributes, it's best to use them together.
Columns Attributes: span, align, valign and width
Our colgroup's and col's can have spanning assigned to them. This doesn't actually collapse multiple cells into one like the rowspan or colspan attributes on a cell. It simply allows for a short-hand way of specifying attributes across multiple columns.
<colgroup> <col /> <col /> </colgroup> <colgroup> <col /> <col /> <col /> </colgroup>
...can also be written as...
<colgroup span="2" /> <colgroup> <col span="2" /> <col /> </colgroup>
The span attribute on the colgroup indicates that the colgroup spans two columns. No col elements are used when a span attribute is present on a colgroup. If col elements do exist in a colgroup then the span attribute on the colgroup is ignored. The span attribute on the col element also indicates that there are two columns.
Next are the align and valign attributes. These can be applied to both the colgroup and col elements and work much like their cell-based versions. Setting align="right" on a column should set the text of every cell within that column to the right. These attributes are important as well because there is no CSS standard for using the text-align property on col or colgroup. Therefore, text alignment needs to be set at the HTML level. Unfortunately, Mozilla don't support the setting of align on a colgroup as of yet. IE does support text-align to be set at the CSS level even though it's not in the spec but best to stay with the HTML approach to keep things more forward compatible.
The width attribute can be specified using one of the three formats:
width="100" width in pixels
width="20%" width in percentage
width="2*" relative width indicating that the cell should be twice as wide as a regular cell. This relative sizing doesn't work in IE or Opera so I'd likely avoid it.
Also good to note is that using a percentage or relative width in IE expands the overall table to 100%, whereas in the versions of Mozilla and Opera that I tested in, it collapsed to the smallest area required to fill the cells — the expected behaviour.
In Part 2, we'll look to give this table a little more style using CSS.
There's another facet to creating your table structure that I haven't touched on here and that is accessibility. This is definitely a topic that needs to be covered on its own. Be sure to check out Table rendering by non-visual user agents and Tablin, a table linearization tool.
For More Information:
- Designing Data Part 2: Adding Style
- Tables as defined in the HTML4.01 Standard (from which XHTML 1.0 is based)
- W3C Notes on Tables
Update: It seems someone took the time to translate this into Russian. Many thanks!