Tables, like lists, are tools for organizing multiple items within Web pages. Whereas lists are used to present several items organized in a linear fashion along a single dimensions, tables are used to present several items organized along two dimensions at the same time.
Tables have historically been used by many Web authors as a tool for page layout. That is, tables are used to arrange the elements that comprise a page, allowing the page author to specify the positioning and spatial relationships among the parts of the page. Although Cascading Style Sheets (CSS) is increasingly being used for this purpose instead, we will examine this way of using tables so that you will understand it if you encounter it. However, you should not use tables for layout purposes in this class. We will use CSS for this purpose.
This page was written to provide students in my CS403 class
with a simple sample document that demonstrates the use of tables discussed
in class. As with the other sample documents I have provided, the primary
motivation has been to generate a relatively simple, but realistic,
document that not only reviews the concepts presented in
lecture, but also demonstrates their use in a
real world
situation.
To get the most out of this document, you should first read it and then study the source that the browser rendered in order to produce it. Use your browser’s ability to display the source of a document for this purpose.
Tables are used to organize data into rows and columns. However, they are extremely flexible and often adapted to other purposes. The most common adaptation of tables is to use them for page layout. And although this use of tables is not recommended by the applicable standards, it is a relatively common practice among Web authors. As such, this documented discusses tables in terms of both their recommended and non-recommended uses.
The <table> element is used to create tables. Within the <table>
element there must be one or more <tr> elements, one for each row
of the table. Within each <tr> element, there must be one or more
<td> and/or <th> elements, one for each cell within that row.
The <td> element defines a standard data cell, while the <th>
element defines a table header cell.
Table header cells are meant to represent headers for rows or columns, but may be used anywhere within a table. Table header cells differ from standard data cells in the default presentation of their contents. However, structurally they are meant to inform the browser that a cell is acting as a header of some sort, typically to label a row or a column. Therefore, table header cells are most commonly found in the first row and/or first column of a table.
Each cell of a table may contain a variety of XHTML elements, including paragraphs, divisions, line breaks, headings, images, and virtually any other page component that XHTML supports. Table cells may also contain other tables. A table that is defined within a cell of another table is called a nested table. Nested tables should be used with caution, however, since they can significantly increase the processing load on a browser. Table cells may also be left empty, if appropriate.
Below is a very simple table with four rows and three cells in each row. All of the cells in the first row are table header cells and the first cell in each row is a table header cell as well. Although this is by no means a requirement, it is a common enough occurrence that the example is typical.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
Examine the source code for the table above. Note the following points:
<tr> elements within the <table> element.
The first one represents the first row of the table, the second one
represents the second row of the table, and so on.<tr> elements contains four <td> and/or
<th> elements, which accounts for the four columns in the table.Tables often have internal subdivisions, and it is advisable to represent such subdivisions structurally whenever appropriate.
Virtually all tables have one or more body rows that primarily represent the data presented by the table. These rows generally make up most, if not all, of the table, and as such can sometimes add up to a significant number of rows. To allow the user agent (i.e., the browser) greater flexibility in displaying these body rows, it is advisable to surround them with a <tbody> element. Doing so allows the user agent to display the body of the table as a scrollable subregion of the page and/or allows you as a Web author to style the body rows distinctly.
Many tables begin with one or more rows that comprise headers for the table, groups of columns or individual columns as necessary. Gathering these rows together within a <thead> element allows the user agent to identify them as distinct from the body rows. A user agent might capitalize upon this knowledge by holding these rows fixed if the body rows are treated as a scrollable subregion or repeating them at the top of each page when printing a lengthy table. And, of course, having this additional structural information in place makes it easier to style the header rows separately from the body rows.
Occasionally, tables end with one or more rows that comprise footers for the table, groups of columns or individual columns as necessary. Using a <tfoot> element to gather these rows together provides similar advantages to those discussed above regarding the <thead> element.
Below is the simple table from the previous example.
It does not look any different here than it did above, but if you examine the source code, you will see that it has been divided into sections using a <thead> element for the first row, a <tbody> element for the middle two rows, and a <tfoot> element for the bottom row.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
Tables may optionally have a caption that describes the purpose of the
table as a whole. To create a caption for a table, use the <caption>
element. The <caption> element must appear immediately after the
<table> start tag, and its contents should be text for the browser
to use in describing the table.
The example below adds a caption to the previous table.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
A table is surrounded by a frame, and the cells within a table are separated from one another by lines called rules. By default, neither the frame nor the rules are visible. There are a variety of ways to control the appearance of the frame and rules.
The recommended way to control a table’s frame and rules is by
using Cascading Style Sheets (CSS). However, it can also be accomplished
using attributes of the <table> element. For the moment, we will
examine the attributes. We will cover CSS later.
The most commonly used attribute for making the frame and rules visible
is the <table> element’s border attribute. The
value of the border attribute sets the width of the table’s
frame. If the value of the border attribute is set to 0,
neither the frame nor the rules will be displayed. If the value of the
border attribute is greater than 0, the frame will be displayed
at that width in pixels. When the frame is displayed, so are the rules;
however, the width of the rules is not affected by the value of the
border attribute.
The example that follows is identical to the previous example with the
simple addition of a border attribute set to a value of 1.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
In some browsers, the first cell in the first row of this table will not
be displayed because it has no contents. To get this cell to reliably appear,
put something in it. A non-breaking space ( ) is commonly
used to add content to a cell while allowing it to appear as if that
cell is empty. Compare the following version of the table, where a
non-breaking space has been inserted into the first cell of the first
row.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
In the next example, the border attribute has been given a
value of 10. Note that this creates a noticeable change in the width of
the frame surrounding the table, but has no impact on the width of the
rules between the cells.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
To provide more specific control over the frame, the <table>
element accepts a frame attribute. There are several possible
values for this attribute:
voidborder or boxvsideshsideslhsrhsabovebelowThe example below uses a frame attribute set to a value
of vsides. It does not use a border attribute. This causes
different browsers to render the rules between cells differently. Try
viewing the following example in a variety of browsers.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
Compare the example above to the one below, which is identical except
for the use of a border attribute with a value of 10.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
To provide more specific control over the rules, the <table>
element accepts a rules attribute. There are several possible
values for this attribute:
noneallrowscolsgroupsThe example below uses a rules attribute set to a value
of rows. It does not use a border attribute. This causes
different browsers to render the frame and rules differently. Try
viewing the following example in a variety of browsers.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
Compare the example above to the one below, which is identical except
for the use of a border attribute with a value of 10.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
To control the thickness of the rules between the cells, use the <table>
element’s cellspacing attribute. The value of this attribute
must be a number indicating the desired rule thickness in pixels. The example
below uses a border attribute with a value of 1 and a
cellspacing attribute with a value of 10.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
Since the rules occupy space even when they are invisible, the
cellspacing attribute may be used, even when the rules
are invisible, to control the space between cells. Consider the
following example which is identical to the previous one with the
border attribute removed.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
Note that the rules surround all the cells of the table equally,
including those cells around the outer edges. Therefore, setting
the value of the cellspacing attribute also serves
to increase the spacing between the outside cells and the table’s
frame. For instance, examine the following table which has a
border attribute value of 20 and a cellspacing
attribute value of 10.
| East | Central | West | |
|---|---|---|---|
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
Normally, each cell of a table is one column wide and one row high. In
some circumstances, however, it is useful to create tables with certain cells
that span more than one column and/or row. To accomplish this, each <td>
and <th> element accepts both a colspan attribute and a
rowspan attribute. For example, a <td> element with a
colspan attribute set to a value of 3 would span across three
columns of the table.
In the following example, notice how a cell was added to act as a header
for the rightmost three columns. To accomplish this, a new row was added
at the top of the table. This row contains only two <th> elements.
One spans only the first column (so it does not need a colspan
attribute) and the other spans the remaining three columns (using a
colspan attribute with a value of 3. Since they span four
columns between them, these two cells suffice, even though the other rows
all contain four cells.
| Division | |||
|---|---|---|---|
| East | Central | West | |
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
Notice how awkward the table now looks with two empty cells
in the upper left. The next example attempts to improve
the appearance of the table by merging these two cells into
one. The first cell in the first row is given a rowspan
attribute with a value of 2. This causes the cell to span both the
first and second columns. Since this cell is now occupying the
first column in the second row, the second row of the table only
needs to contain three cells for the remaining columns.
| Division | |||
|---|---|---|---|
| East | Central | West | |
| Income | $845,943 | $656,742 | $732,882 |
| Expenses | $543,432 | $732,403 | $738,239 |
| Profit/Loss | $302,511 | -$75,661 | -$5,357 |
Although CSS is now recommended for performing page layout, Web authors have traditionally made extensive use of tables for this purpose. Since students are likely to encounter this use of tables in code and interact with other Web authors and tutorial resources that advocate this approach, I have decided to give you enough information to recognize this technique when you see it, despite the fact that it is not recommended by the standards.
Page layout refers to the process of organizing the components that comprise a Web page. For many years, tables were the only mechanism available within HTML to organize and arrange the parts of a page. Several factors contributed to the flexibility that made tables attractive for this purpose:
However, tables are really not intended for this purpose: they are meant to be used for the presentation of data organized into rows and columns. As such, they are not ideal for page layout. They have several shortcomings when used for page layout:
CSS is the currently preferred mechanism for page layout. It offers greater flexibility and accessibility. However, since browsers only recently began supporting this use of CSS, many Web authors have used tables for layout despite the recommendation of the standards to the contrary.
When a table is used for page layout. it is generally nested directly within
the <body> element. Everything else within the page is then nested within
the cells of the layout table. Therefore, when using a table for page layout
is generally best to start with a sketch of what you want to achieve. Then,
design a <table> element that will accommodate that design. And finally,
once the table is complete, place the code to produce the different components
of the page within the appropriate cells in that table.
Unfortunately, there is no way to provide a sample of a complete page using a table for its layout as a part of this page. There are, however, literally millions of pages on the Web that use this technique. Therefore, you should not need to look far to find as many examples as you care to examine.
Below, I will briefly outline the process used to develop a table based layout.
Generally, the first step in using a table for page layout is to sketch the general structure you envision for the page. Draw out the rough proportions of each component area on the page and label each one as a reminder of the purpose that area is meant to serve.

The next step is to identify the number of rows and columns that the underlying table would require if it were a “regular” table. This is because we start with a “regular” table and then make individual cells span multiple columns and/or rows as necessary to establish the “irregular” table we need to realize our vision for the layout.
To accomplish this, simply extend each line within the initial sketch so that it runs across the entire width or height of the table. I recommend using dotted and/or different colored lines so the extensions can be easily recognized. With each line extended, the underlying regular table will be easy to see.
In the example below, the table consists of six rows and three columns.
We therefore know that our <table> element will need to
contain six <tr> elements.

Next we determine the rows and/or columns each cell must span to implement our initial sketch as an actual table. For each component area in the sketch, use the line extensions to determine how many rows and/or columns it will need to span. Write your findings for each area right on the sketch as shown below:

Finally, we can use our sketch to implement a table that occupies the entire body of the page we intend to layout. Work through the XHTML for the table one row at a time from top to bottom. Be careful to keep track of where you are in the sketch and which cells in the current row have already been accounted for by cells spanning rows from above.
