Tables

One of the most complex structures in HTML is the table. In its proper form, a table is essentially a two-dimensional list with the option of labels. More precisely, it is HTML‘s version of the spreadsheet The table uses quite a large set of elements.

All table elements work as block elements, and all use the core and language attributes.

Simple Tables

Most table elements consist of the table element, table rows, and table cells, with the option of a caption. These are simple tables.

Table Elements

The following elements will make for a perfectly suitable table.

The Table Element

Element Name: table

The table element contains all other elements associated with a table. It is a block element.

Implied Attributes
summary
The summary attribute contains a summary of the table’s contents, in case a user agent has difficulty rendering a table (some do).

The Table Caption Element

Element Name: caption

The caption element — which is an optional element, but comes first in any table should you use it — is used to give your table a title.

The Table Row Element

Element Name: tr

Table cells cannot be stored directly in the table element — they must be arranged in rows. This is the job of the tr element: It creates the rows that the cells are in.

The Table Header Cell and Table Data Cell Elements

Element names:

th
Table Header Cell Element
td
Table Data Cell Element

These element are paired together because they contain similar functions and attributes. They can contain either plain text (which is normally the case) or any body element — including tables. If you’re nesting tables, though, you might be going overboard.

Implied Attributes
headers
This attribute is an IDREFS-type attribute — in other words, it’s a reference to an ID attribute elsewhere. It’s usually used in a td element to reference the id attribute in the th at the head of the td element’s column.
rowspan
For various reasons, sometimes a cell is supposed to span two or more rows (stretching it vertically). This attribute is numerical.
colspan
For various reasons, sometimes a cell is supposed to span two or more columns (stretching it horizontally). This attribute is numerical.

An Example Table

To demonstrate tables, I’ve included one that would look exactly how it would normally, and the same table with borders added so that you can see just what is going on.

A table comparing binary, octal, decimal, and hexidecimal numbers.
A table comparing binary, octal, decimal, and hexidecimal numbers with a border added.

The Code Of the Above Table
(IDs and Their Respective Headers Are Color-Coded)

<table summary="Compares binary, octal, decimal, and hexadecimal notation.">
<caption>Binary, Octal, Decimal, Hexadecimal</caption>
<tr>
<th id="Part_2-Chap_14-BIN">Binary</th>
<th id="Part_2-Chap_14-OCT">Octal</th>
<th id="Part_2-Chap_14-DEC" rowspan="2">Decimal</th>
<th id="Part_2-Chap_14-HEX">Hexadecimal</th>
</tr>
<tr>
<th headers="BIN">(Base 2)</th>
<th headers="OCT">(Base 8)</th>
<th headers="HEX">(Base 16)</th>
</tr>
<tr>
<td headers="BIN OCT DEC HEX" colspan="4">0</td>
</tr>
<tr>
<td headers="BIN OCT DEC HEX" colspan="4">1</td>
</tr>
<tr>
<td headers="BIN">10</td>
<td headers="OCT DEC HEX" colspan="3">2</td>
</tr>
<tr>
<td headers="BIN">11</td>
<td headers="OCT DEC HEX" colspan="3">3</td>
</tr>
<tr>
<td headers="BIN">100</td>
<td headers="OCT DEC HEX" colspan="3">4</td>
</tr>
<tr>
<td headers="BIN">101</td>
<td headers="OCT DEC HEX" colspan="3">5</td>
</tr>
<tr>
<td headers="BIN">110</td>
<td headers="OCT DEC HEX" colspan="3">6</td>
</tr>
<tr>
<td headers="BIN">111</td>
<td headers="OCT DEC HEX" colspan="3">7</td>
</tr>
<tr>
<td headers="BIN">1000</td>
<td headers="OCT">10</td>
<td headers="DEC HEX" colspan="2">8</td>
</tr>
<tr>
<td headers="BIN">1001</td>
<td headers="OCT">11</td>
<td headers="DEC HEX" colspan="2">9</td>
</tr>
<tr>
<td headers="BIN">1010</td>
<td headers="OCT">12</td>
<td headers="DEC">10</td>
<td headers="HEX">A</td>
</tr>
<tr>
<td headers="BIN">1011</td>
<td headers="OCT">13</td>
<td headers="DEC">11</td>
<td headers="HEX">B</td>
</tr>
<tr>
<td headers="BIN">1100</td>
<td headers="OCT">14</td>
<td headers="DEC">12</td>
<td headers="HEX">C</td>
</tr>
<tr>
<td headers="BIN">1101</td>
<td headers="OCT">15</td>
<td headers="DEC">13</td>
<td headers="HEX">D</td>
</tr>
<tr>
<td headers="BIN">1110</td>
<td headers="OCT">16</td>
<td headers="DEC">14</td>
<td headers="HEX">E</td>
</tr>
<tr>
<td headers="BIN">1111</td>
<td headers="OCT">17</td>
<td headers="DEC">15</td>
<td headers="HEX">F</td>
</tr>
<tr>
<td headers="BIN">10000</td>
<td headers="OCT">20</td>
<td headers="DEC">16</td>
<td headers="HEX">10</td>
</tr>
</table>

Complex Tables

Simple tables as described above are essentially a shortcut. A complete table is divided into several sections, depending on content. Note: The caption element (if you use it) always goes before any of the following elements.

The core and language attributes may be used with all elements mentioned here.

Table Section Elements

Tables are divided into three main sections, depending on their content: the table head, the table foot, and the table body. All three elements must have the same number of columns, or your table won’t look right (using the colspan attribute counts).

The Table Header Element

Element Name: thead

The thead element is used to contain the column headers. You may use only one thead element.

The Table Footer Element

Element Name: tfoot

The tfoot element — which is an optional element, goes at the bottom of the table, and is usually used for footnotes or even a reiteration of table headers if the table is particularly long. Yes, it does go before the table body, even though it appears afterwards.

The reason for this is an HTML document is always processed from top to bottom. (This is why you should have your base element before your link elements).

Thus, if the browser fails to download the entire table (which is possible), the tfoot element will still be processed.

You may use only one tfoot element.

The Table Body Element

Element Name: tbody

The tbody element contains the main body of your table data. You may use as many tbody elements as you please, so long as you have at least one.

Table Columns

Aside from rows, tables also use columns, which control how cells in specific columns look: their width, hight, the vertical alignment of their contents, and so on. Nowadays, you can use Cascading Style Sheets to control this, but columns are still a part of the HTML 4.01 Strict specification, so I’m mentioning them here, along with their more common attributes.

The Column Element

Element Name: col

The col element normally controls the appearance of a single column (unless more are specified).

The col element is an empty element It has no end tag.

Implied Attributes
span
This numeric attribute allows a col element to control more than one column.
width
This numeric attribute sets the width of the column in pixels.

The Column Group Element

Element Name: colgroup

The colgroup element is used to put col elements into groups. It can also be used on its own.

Implied Attributes
span
This numeric attribute allows a col element to control more than one column.
width
This numeric attribute sets the width of the column in pixels.

Usage Of colgroup And col Elements

The colgroup and col elements go after the caption element but before any others.

You may have col elements on their own, colgroup elements without children, or col elements nested in colgroup elements. What may not be done is a mixture of colgroup elements and lone col elements.

In other words, the first two following examples are valid, but the third is not.

col Elements On Their Own

<col width="100">
<col span="2" width="200">
<col width="100">
colgroup Elements

<colgroup width="100">
<col>
<col span="2" width="200">
<col>
</colgroup>
<colgroup span="3" width="150">
</colgroup>
col Elements Outside colgroup Elements (Invalid)

<col width="100">
<col span="2" width="200">
<col width="100">
<colgroup width="100">
<col>
<col span="2" width="200">
<col>
</colgroup>
<colgroup span="3" width="150">
</colgroup>

An Example Complex Table

To demonstrate tables, I’ve included one that would look exactly how it would normally, and the same table with borders added so that you can see just what is going on. This is similar to the table from Chapter 12. Do note the disadvantage of using multiple tbody elements: the rowspan attribute will not allow a cell to stretch beyond its ancestor tbody element.

A table comparing binary, octal, decimal, and hexidecimal numbers.
A table comparing binary, octal, decimal, and hexidecimal numbers with borders added.

The Code Of the Above Table
(IDs and Their Respective Headers Are Color-Coded)
(thead, tfoot, and tbody Tags Are Underlined.)
(The Column Elements Are In Italics.)

<table summary="Compares binary, octal, decimal, and hexadecimal notation.">
<caption>Binary, Octal, Decimal, Hexadecimal</caption>
<colgroup>
<col span="2" width="100">
<col span="3" width="60">
</colgroup>
<thead>
<tr>
<th class="RowHead">Number System:</th>
<th id="Part_2-Chap_14-BIN">BIN</th>
<th id="Part_2-Chap_14-OCT">OCT</th>
<th id="Part_2-Chap_14-DEC">DEC</th>
<th id="Part_2-Chap_14-HEX">HEX</th>
</tr>
</thead>
<tfoot>
<tr>
<th class="RowHead">DIGITS:</th>
<td headers="BIN">0, 1</td>
<td headers="OCT">0, 1, 2, 3, 4, 5, 6, 7</td>
<td headers="DEC">0, 1, 2, 3, 4, 5, 6, 7, 8, 9</td>
<td headers="HEX">0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F</td>
</tr>
<tr>
<td colspan="5">
<dl>
<dt>BIN</dt>
<dd>Binary (Base 2)</dd>
<dt>OCT</dt>
<dd>Octal (Base 8)</dd>
<dt>DEC</dt>
<dd>Decimal (Base 10)</dd>
<dt>HEX</dt>
<dd>Hexadecimal (Base 16)</dd>
</dl>
</td>
</tr>
</tfoot>
<tbody id="Part_2-Chap_14-BIN_OCT_DEC_HEX_Match">
<tr>
<th class="RowHead" rowspan="2">Number Comparisons</th>
<td headers="BIN OCT DEC HEX" colspan="4">0</td>
</tr>
<tr>
<td headers="BIN OCT DEC HEX" colspan="4">1</td>
</tr>
</tbody>
<tbody id="Part_2-Chap_14-OCT_DEC_HEX_Match">
<tr>
<th class="RowHead" rowspan="6">Number Comparisons</th>
<td headers="BIN">10</td>
<td headers="OCT DEC HEX" colspan="3">2</td>
</tr>
<tr>
<td headers="BIN">11</td>
<td headers="OCT DEC HEX" colspan="3">3</td>
</tr>
<tr>
<td headers="BIN">100</td>
<td headers="OCT DEC HEX" colspan="3">4</td>
</tr>
<tr>
<td headers="BIN">101</td>
<td headers="OCT DEC HEX" colspan="3">5</td>
</tr>
<tr>
<td headers="BIN">110</td>
<td headers="OCT DEC HEX" colspan="3">6</td>
</tr>
<tr>
<td headers="BIN">111</td>
<td headers="OCT DEC HEX" colspan="3">7</td>
</tr>
</tbody>
<tbody id="Part_2-Chap_14-DEC_HEX_Match">
<tr>
<th class="RowHead" rowspan="2">Number Comparisons</th>
<td headers="BIN">1000</td>
<td headers="OCT">10</td>
<td headers="DEC HEX" colspan="2">8</td>
</tr>
<tr>
<td headers="BIN">1001</td>
<td headers="OCT">11</td>
<td headers="DEC HEX" colspan="2">9</td>
</tr>
</tbody>
<tbody id="Part_2-Chap_14-No_Match">
<tr>
<th class="RowHead" rowspan="7">Number Comparisons</th>
<td headers="BIN">1010</td>
<td headers="OCT">12</td>
<td headers="DEC">10</td>
<td headers="HEX">A</td>
</tr>
<tr>
<td headers="BIN">1011</td>
<td headers="OCT">13</td>
<td headers="DEC">11</td>
<td headers="HEX">B</td>
</tr>
<tr>
<td headers="BIN">1100</td>
<td headers="OCT">14</td>
<td headers="DEC">12</td>
<td headers="HEX">C</td>
</tr>
<tr>
<td headers="BIN">1101</td>
<td headers="OCT">15</td>
<td headers="DEC">13</td>
<td headers="HEX">D</td>
</tr>
<tr>
<td headers="BIN">1110</td>
<td headers="OCT">16</td>
<td headers="DEC">14</td>
<td headers="HEX">E</td>
</tr>
<tr>
<td headers="BIN">1111</td>
<td headers="OCT">17</td>
<td headers="DEC">15</td>
<td headers="HEX">F</td>
</tr>
<tr>
<td headers="BIN">10000</td>
<td headers="OCT">20</td>
<td headers="DEC">16</td>
<td headers="HEX">10</td>
</tr>
</tbody>
</table>