Tables and CSS should be friends.

A lot of web pages use tables for layout. It was how complicated web pages were constructed before CSS, and still, in many instances, is the easiest way to do layout. The problem with tables for layout is that content and style become very inter-dependent. The programmers can't go home until the artists have finished, and the artists have to rejigger designs after the programmers apply a bug fix. With automatically generated pages with PHP (or ASP, or servlets), this becomes a major development roadblock.

Having decided to use both tables and CSS the idea would be to use the minimum of attributes in the table tags, and the maximum of CSS properties by either clever use of selectors.

Basic Table

The basic idea is that a table is a sequence of rows, and each row is a sequence of cells. The contents of a cell is bracketed with either TH or TD tags. According to the standard, closing tags for TH and TD are optional, it will validate for HTML 4.01 Strict without them.

Then multiplicity of consecutive cells are bound into a row by place them between TR tags, and the collection of rows is bound into a table by place them between TABLE tags. The closing TABLE tag is not optional.

The HTML and CSS How it renders
<table>
<tr>
<th>One
<th>Two
<th>Three
<tr>
<td>1
<td>2
<td>3
</table>
One Two Three
1 2 3

The difference between TH and TD is just the formatting of the contents of the cell. The default formatting makes TH the appropriate tag for the heading cells of the table: boldface type and centered, for instance. When adding custom styling it provides a convenient way to target certain cells for one styling and other cells for anohter. Again, for the purpose of heading cells and data cells.

The COL tag

Formatting for a row can be applied to the TR tag, and will govern formatting for all cell elements in that row. Formatting for a column can be achieved by using the COL tag to reference a table column. Unlike the TR tag, the COL tag has no content. It creates a nameable entity out of a bunch of cells, those in a single column, and allows style to be applied to all those cells.

The HTML and CSS How it renders
<style type="text/css">
   #example-coltag col { width: 4em; }
   #example-coltag .heading { 
                         background: #ccc; }
   #example-coltag .c1 { background: #9ff; }
   #example-coltag .c2 { background: #f9f; }
   #example-coltag .c3 { background: #afa; }
   #example-coltag .c4 { background: #faa; }
</style">
...
<table id="example-coltag">
<col class="c1">
<col class="c2">
<col class="c3">
<col class="c4">
<tr><th>One<th>Two<th>Three<th>Four
<tr><td>1<td>2<td>3<td>4
<tr><td>1<td>2<td>3<td>4
<tr><td>1<td>2<td>3<td>4
<tr><td>1<td>2<td>3<td>4
</table>
OneTwoThreeFour
1234
1234
1234
1234

The col and colgroup tags have background, border, width and visibility. For the border property to be effective, however, the table must have its borders collapsed.

Also, the COL tag has a width attribute that can take a Proportional Unit. As an example, 3* means a width equal to three times the natural column width, as determined by the layout algorithm. The CSS friendly col { width: 3*; } does not work.

The colgroup tag can be used either with span attribute or by enclosing col tags. In the following example, two column groups are formed. The first specifies columns one and two using a span. The second specifies the remaining three columns are grouped by enclosing three col tags.

The HTML and CSS How it renders
<style type="text/css">
  #eg-colgp { margin: auto; 
      border-collapse: collapse; }
  #eg-colgp col { width: 4em; 
      border: 1px solid yellow; }
  #eg-colgp th { background: #ccc; 
      border: 1px solid blue ; }
  #eg-colgp colgroup { width: 5em;
      border: 2px solid red; }
  #eg-colgp .g1 { background: #9ff; }
  #eg-colgp .g2 { background: #afa; }
  #eg-colgp .c3 { background: #f9f; }
  #eg-colgp .c5 { background: #faa; }
</style>
...
<table id="eg-colgp">
<colgroup class="g1" span=2>
<colgroup class="g2">
<col class="c3">
<col class="c4">
<col class="c5">
</colgroup>
<tr><th>One<th>Two<th>Three<th>Four<th>Five 
<tr><td>1<td>2<td>3<td>4<td>5
<tr><td>1<td>2<td>3<td>4<td>5
<tr><td>1<td>2<td>3<td>4<td>5
</table>

OneTwoThreeFourFive
12345
12345
12345

The table elements are rendered in priority six planes. From top to bottom they are: cells, rows, columns, column groups and table. In this example, the background property shows this effect. The left column group is set to aqua, and the right to grey. The columns are in set to purple and green using class tags. Since columns are above column groups, their color shows. Also the th tag gives the header a color. Since this is on the cell plane it shows above the other colors.

Border collapse is requested, so the border properties operate. Borders are not in planes. They are resolved by a rule stating that the most important border shows. A more important border is either thicker, or is in a more instant style, e.g. solid over dashed, and there are some other rules. In this example, the red column group border is thick, so it shows everywhere. The yellow column border is applied to the Three Four and Five columns. The One and Two columns have no col tag to receive the inheritance, and therefore there are one borders in these columns.

The colgroup has width property of 5em. The col has width property of 4em. Since cols are inside of colgroups, they override the width property in the example. Note that width for a colgroup is the width of the cells, not of the column group.

But how does this jive with the insertion of anonymous col's and colgroup's?

Spanning rows and columns

It was mentioned that the best approach is to push as much formatting into CSS properties (although this might mean forgoing some old school table attributes). COLSPAN and ROWSPAN are TH or TD attributes which are not going away. It does seen that spanning is a structural property of a table, not a formatting issue, so this should not cause any personal friction between tables and style sheets.

Here is a simple example using the colspan attribute.

The HTML and CSS How it renders
<style type="text/css">
   #example-colspan col { width: 4em; }
   #example-colspan .c1 { background: #9ff; }
   #example-colspan .c2 { background: #f9f; }
   #example-colspan .c3 { background: #afa; }
   #example-colspan .c4 { background: #faa; }
</style>
...
<table id="example-colspan">
<col class="c1">
<col class="c2">
<col class="c3">
<col class="c4">
<tr><th>One<th>Two<th>Three<th>Four
<tr><td>1<td>2<td>3<td>4
<tr><td>1<td>2<td colspan="2">3
<tr><td>1<td colspan="2">2<td>3
<tr><td colspan="2">1<td>2<td>3
</table>
OneTwoThreeFour
1234
123
123
123

Here is an example combining borders and column span.

OneTwoThreeFour
1234
123
123
123
More to come ...