[XHTML2][CSS3] Tables: A proposal to support styling by columns

Well, I said earlier on www-style that column styling might require
revisiting the XHTML table model, altho I hoped it wouldn't  Well,
I am now convinced that it will, altho the changes are fairly minor
and only affect tables that use the rowspan and/or colspan attributes.

A Proposal For the XHTML 2 Table Module and the CSS3 Table Module
To Enable Styling By Columns via CSS

One of the most requested features for CSS is to provide a mechanism
to enable styling columns via CSS.  This can actually be done now
for simple cases, but complex cases cause problems.

Example 1:
<!-- An HTML4/XHTML1 table -->
<table>
  <tr><th>1</td><th>2</th><th>3</th></tr>
  <tr><th>4</td><td>5</td><td>6</td></tr>
  <tr><th>7</td><td>8</td><td>9</td></tr>
</table>

The selector "tr>*:last-child" selects the cells in the last column
quite nicely.  More generally, the selector "tr>*:nth-child(k)"
selects the cells from column k. The difficulty comes when trying 
to handle more complicated cases where colspan and rowspan are used,
or where unusual values of the display property are chosen..

Example 2:
<!-- An HTML4/XHTML1 table -->
<table>
  <tr><th>1</td><th>2</th><th>3</th></tr>
  <tr><th>4</td><td rowspan="2">5<br />8</td><td>6</td></tr>
  <tr><th>7</td><td>9</td></tr>
</table>

Here the selector "tr>*:nth-child(2)" will select the cell with content
"9" which is actually in the third column.  The problem occurs because
of the HTML table model which dates from before the time it was decided
that separating styling from content would be a good thing to do.  There
is no need in unstyled HTML to indicate in the third table row anything
about the second column to achieve the correct layout.  Hence, why
include such an element was the thinking, and thus HTML was designed
to not use it.

Unfortunately, CSS needs to determine style before it can determine
layout.  The CSS display properties and the table layout algorithm
combine to make it impossible to determine the column of an element in
a manner that would not be changed if the value of display is changed
for one or more of the table elements.

However, what if we change the table layout model for unstyled tables.
A small change was made between HTML4 and XHTML1 where the table rules
were changed to use the CSS 2 table layout algorithm instead.  If CSS 3
includes changes to make column selection possible, then a change in
the default table layout rules for XHTML2 to support this would be
desirable.  Changing the rules so that the value of rowspan and colspan
do not affect the column that a sibling element is in would enable the
selector "tr>*:nth-child(k)" to select the cells from column k.

Consider the following example taken from CSS 2.1 Section 17.5: [1]

Example 3:
<table>
<tr><td>1 </td><td rowspan="2">2 </td><td>3 </td><td>4 </td></tr>
<tr><td colspan="2">5 </td></tr>
</table>

Treated as HTML4, this table is erroneous and could be presented
with cells 2 and 5 overlapping, while as XHTML1 using the CSS2
table layout rules it would not be overlapping. [2]

CSS2 considers overlapping cells to be a bad thing, but is it?
Suppose that overlapping cells were allowed and that rowspan
and colspan simply indicated the amount of overlap.

Example 4:
<!-- An XHTMLish table corresponding to Example 2 -->
<table>
  <tr><th>1</td><th>2</th><th>3</th></tr>
  <tr><th>4</td><td rowspan="2">5<br />8</td><td>6</td></tr>
  <tr><th>7</td><td/><td>9</td></tr>
</table>

Here the rowspan attribute instead of indicating that there is no need
to provide an element in the third row for the second column, indicates
that a default visual presentation will cause the contents of the cell
in row 2, column 2, to overlap the cell below it.

To handle this with CSS requires a new property:

---

'table-cell-overlap'
Value:          none|clapboard|inherit
Initial:        none
Applies to:    'table' and 'inline-table' elements
Inherited:      no
Percentages:    N/A
Media:          visual
Computed value: as specified

none
Cells are laid out so that they do not overlap.  This was the only
possibility in the CSS 2 table layout model, which is why this is the
initial value of this new property.

clapboard
Cells are laid out so that the they overlap in the following fashion.
Each cell is laid out so that table cell encountered first in the
traversal of the table will be in front of later table cell.  This
effect is similar to that of clapboard siding which is where the name
of this value comes from.  In interactive media, if focus is placed upon
a table cell in a table with this value for table-cell-overlap then it
will be presented in front of all other cells in that table.

---

There may be other models for overlap that make sense, so this proposed
property has been designed so that it is easy to add to, which is another
reason why I did not name clapboard, "auto", or any other similar phrase
that would tend to indicate that it is the only reasonable possibility.

This handles the column problem as far as CSS is concerned adequately,
but there is still a problem as far as XHTML2 is concerned.  Rowspan
and colspan are almost entirely presentational, but not quite.

As far as the semantics of the <table> element are concerned, example 2
is a shorthand way of indicating the semantically equivalent table:

Example 5
<!-- An HTML4/XHTML1 table -->
<table>
  <tr><th>1</td><th>2</th><th>3</th></tr>
  <tr><th>4</td><td>5<br />8</td><td>6</td></tr>
  <tr><th>7</td><td>5<br />8</td><td>9</td></tr>
</table>

combined with a presentation that collapses the two adjacent cells with
identical content into a single cell.  Example 4 handles the presentation
adequately, but not the semantics, as it doesn't indicate what the
content of the cell in row 3, column 2 is.  Duplicating the content as
per example 5 is troublesome if the content is fairly large.  Using XML
Inclusion (XInclude) would work:

Example 6
<!-- An HTML4/XHTML1 table with XInclude-->
<table>
  <tr><th>1</td><th>2</th><th>3</th></tr>
  <tr><th>4</td><td id="a">5<br />8</td><td>6</td></tr>
  <tr><th>7</td><xi:include xpointer="a" /><td>9</td></tr>
</table>

Example 6 is essentially the same as example 5 and to achieve a visual
presentation of example 6 identical to example 2 one would only need
the following style rules:

#a {rowspan:2}
xi|include {visibility:hidden}

assuming that "rowspan" and "colspan" are defined as CSS properties
such as:

---

'colspan'
'rowspan'

Value:          <integer>|inherit
Initial:        1
Applies to:    'table-cell' elements
Inherited:      no
Percentages:    N/A
Media:          visual
Computed value: as specified

---

However, the full capabilities of even a minimal XInclude implementation
are not needed for this purpose.  We neither need nor want any of the
attributes of xi:include other than xpointer.  This suggests we may want
to use a special purpose element.

Example 7
<!-- An XHTMLish table -->
<table>
  <tr><th>1</td><th>2</th><th>3</th></tr>
  <tr><th>4</td><td id="a">5<br />8</td><td>6</td></tr>
  <tr><th>7</td><tc tref="a" /><td>9</td></tr>
</table>

The <tc> element would take but a single attribute tref of type IDREF.
If the tref attribute is missing or if it refers to either a
non-existent element, an element that is not a table cell in the
same table, or itself would be the same as <td/>. Otherwise it would be
the same as if the element had instead been an <xi:include>
element with the value of the tref attribute used as the value of the
xpointer attribute and all other attributes left unchanged.

I'm not 100% certain of how XInclude handles ID's and IDREF's, so I
don't know if this is going to cause any problems.  I don't think it
will, altho it might cause a little oddity here or there.  I think the
intent of my proposal is clear, but if I haven't given an appropriate
description of what the result is, let me know.

[1] http://www.w3.org/TR/CSS21/tables.html#q7
[2] http://www.w3.org/TR/CSS21/images/table-overlap.png

Ernest Cline
ernestcline@mindspring.com

Received on Sunday, 14 December 2003 20:57:35 UTC