22 June 1997
This is a personal memo for consideration by the CSS&FP WG.
This memo outlines the constraints for the CSS table model, suggests (part of) a possible model and the accompanying syntax.
The requirements for the CSS table model are as follows. Some requirements may be more important than others.
There are essentially three possible ways in which a table can be marked up in an SGML document:
The markup represents the desired visual structure, with cells sorted by row. The HTML table model is of this type, as is the TEI model. This is the most common type.
The cells are sorted by column. This is rare. (Note that the HTML table model has elements that represent the columns, but they don't contain the cells.)
The markup represents relationships between elements, but without referring to the visual relations of rows and columns. The visual representation doesn't have to be a table, but could be. The DL element in HTML is of this type.
To make things a bit simpler, we assume that a cell in the table corresponds to an element in the source. A cell may span several columns and rows, but its contents come from a single element, and all that element's content go into the same cell. An element that acts as a cell cannot contain descendants that are also cells in the same table.
To make it easier to know when a table ends, we also assume that all cells have a common ancestor, and that all descendants of that element are either ignored (i.e., not displayed) or can be assigned one of the roles discussed below.
In a visual table, we can distinguish the following elements:
In right-to-left text, the words `left' and `right' above should be reversed.
There are at least three ways of rendering the separators:
Methods 2 and 3 are common in desktop publishing, method 1 is used in some Web browsers, because it works well with the Motif 2½D-look.
A number of examples of tables were collected over a year ago.
In CSS, properties are primarily attached to elements in the source tree. When there are visual areas that do not directly correspond to an element, a pseudo-element may solve the problem. Examples are ":first-letter" and ":marker" (a proposal in WD-frosting).
If there are areas shared by a number of elements, cascading and inheritance are the usual solution.
However, if the shared area is shared among elements that are not in a parent-child relation, an ad-hoc rule is introduced. An example is the treatment of whitespace between paragraphs: the rule is that the largest whitespace wins.
In tables, we have this problem with regard to the borders, if we accept that they are shared, and with regard to the fact that columns and rows both describe the same area, but only one of them is a parent of the cell in the SGML sense.
For borders, I propose to use a rule similar to the vertical margin one: the thickest border wins.
For columns and rows I propose simply that they are regarded as not corresponding to a visual area. That is, (almost) none of the CSS1 properties applies to rows and columns, although they are inherited normally.
How this works out in detail can be seen in a draft specification and in the examples.
Rendering the document structure as a table requires mapping each of the elements that represent a cell to the right column(s) and row(s). Other elements must be mapped to other roles, or be ignored.
Rows and columns can be identified by numbers or by names. Mapping involves finding the right names or numbers for each cell. In some cells the right column or row may be given explicitly, such as in an attribute. Usually, however, the row and column is implicit in the order of the cells. This is the case, e.g., in the HTML table model.
The HTML table model also shows how explicit assignment of cells to rows and columns can be done: AXIS attributes define symnolic names for the rows and columns, while AXES attributes specify the rows and columns to which a cell belongs. But in HTML these attributes are not required, so the renderer cannot rely on them.
This XML fragment shows how explicit (named) relationships between elements could be used to build a table:
<measurements> <time> <label axis="may">May</label> <label axis="jun">June</label> <label axis="jul">July</label> </time> <molecule> <label axis="CO2">CO<sub>2</sub></label> <label axis="NOx">NO<sub>x</sub></label> </molecule> <place> <label axis="ams">Amsterdam</label> <label axis="par">Paris</label> </place> <data> <data axes="may,CO2,ams">327</data> <data axes="may,NOx,ams">12</data> ... </data> </measurements>
There are actually three axes here, so we'll have to choose the main ones. The following renderings could all be made out of the same data:
| May | June | July | ||||
|---|---|---|---|---|---|---|
| CO2 | NOx | CO2 | NOx | CO2 | NOx | |
| Amsterdam | 327 | 12 | ... | ... | ... | ... |
| Paris | ... | ... | ... | ... | ... | ... |
| Amsterdam | Paris | ||
|---|---|---|---|
| CO2 | May | 327 | ... |
| June | ... | ... | |
| July | ... | ... | |
| NOx | May | 12 | ... |
| June | ... | ... | |
| July | ... | ... |
Note that some of the labels had to be repeated, since a 3D table wasn't possible.
The following fragment of HTML shows how implicit ordering of elements defines the position in a table:
<table> <tr><th> <th>Head A <th>Head B <th>Head C <tr><th>Head 1 <td>Data A1 <td>Data B1 <td>Data C1 <tr><th>Head 2 <td>Data A2 <td>Data B2 <td>Data C2 </table>
One rendering could be like this:
| Head 1 | Head 2 | |
|---|---|---|
| Head A | Data A1 | Data A2 |
| Head B | Data B1 | Data B2 |
| Head C | Data C1 | Data C2 |
"Data B1", for example, is the 3rd child of the 2nd child of TABLE, so it it assigned to the 3rd row and the 2nd column.
When elements span columns and rows, the counting can become more difficult.
Last modified: Fri Jun 27 18:39:28 MET DST