Web design: advanced techniques
Tables
HTML tables once played a far greater role in the design of a web page than they do today. The role of a table is quite simply to present a table, or grid of data, much like a spreadsheet. Before CSS, tables were used as a way to place page elements in the browser window, but this produced extremely complicated HTML code that was hard to maintain, and harder yet for non-visual and mobile browsers to read. Today, style-sheets allow far greater control over layout than tables ever did. Still, tables are important for presenting certain kinds of information.
A table is comprised of rows and columns of cells. Columns can be grouped together, and you can distinguish between header cells and data cells, and assign groups of rows as the table header or body. Nice and simple? No, not really. Table-handing is the major function of most HTML editing programs like Dreamweaver and Frontpage. In fact, prior to HTML 4, learning to write and manipulate tables was an essential part of web design: it was the only way to visually lay out page elements anywhere on the screen. Now though, tables are purely for presenting data in grid format, and their complexity can be left to an advanced techniques section such as the one you are reading now.
Table Mark-up
Let's look at a simple table and its HTML code. Tables are written one row at a time, cells declared from left to right for each row. Like an HTML document, tables have a head and a body, though unlike standard HTML documents, both sections are optional; if you omit both, all rows are assumed to be part of the "table body".
<table frame="border" border="1" rules="all" summary="An
example table">Head A
<thead>
<tr>
<th></th>Head B
<th></th>Cell A
</tr>
</thead>
<tbody>
<tr>
<td></td>Cell B
<td></td>Cell C
</tr>
<tr>
<td></td>Cell D
<td></td>
</tr>
</tbody>
</table>
This simple table has three rows (marked by the <tr> tag)
and two columns. The summary="" attribute of the table tag is a required
element that describes the content of the table. The first row contains header
cells (<th>),
and the other two rows contain standard
"data cells" (<td>). As with all HTML, it's
important to use the correct tag, not the one that looks best on screen,
after all you can use CSS to change how cells look, but you cannot change
what tags mean. Having header cells instead of simply standard data cells
allows blind users to
be able
to easily
find
out
which column they are reading. The example above should appear like this:
| Head A | Head B |
|---|---|
| Cell A | Cell B |
| Cell C | Cell D |
One thing you may notice as we continue is that tables provide a rare exception to the "new way" of HTML and CSS: tables in HTML still leave much of the presentation and appearance of the table as attributes to the HTML tags, rather than properties in a style-sheet. This is both because the presentation of a table is very closely linked to the kind of data it holds, and for compatibility with the hundreds of millions of table-based layouts out there.
Splitting the table into head and body sections is strictly optional; you
do not need to use the <thead>, <tbody>,
or <tfoot> tags. The HTML specification says that supplying
them allows browsers to repeat
the header section at the top of every page when printing long tables, and
also allows the table body to be scrolled on screen independently from the
header and footer sections, however at the time of writing, no popular browser
supports these. What can be done with these tags is to apply CSS styles
to sections of your table, and/or to draw grid-lines around them.
Grid-lines and borders in HTML tables are handled by the frame="" and rules=""
attributes. By default, tables have no visible border around the table or
individual cells, but these attributes can be set to draw frames and grid-lines
very specifically for columns, rows, and even groups of rows and columns
like the <thead> and <tbody> row-groups described above. If the table has
a surrounding frame, you can use CSS to define the style of
that frame using the "border" properties, or the border="" attribute.
Which you use is up to you: if you have many similar tables then a CSS
rule will save you time and effort both in writing and maintaining
the layout, but for a single table then the border attribute may be enough.
Spanned cells and column groups
Coding simple grids in HTML is fairly straightforward: you simply type each cell from left to right and mark up the rows. Not all data is so simply displayed though. HTML allows you to name and group several columns together, and also to join adjacent cells together either vertically (with the rowspan="" attribute) or horizontally (with the colspan="" attribute). Here's a more complex example with several spanned cells:
<table frame="border" border="1" rules="all" summary="An example table with spanned
cells">Part number
<thead>
<tr>
<th></th>Description
<th></th>In stock
<th></th>In shop
<th></th>In warehouse
<th></th>RM052
</tr>
</thead>
<tbody>
<tr>
<td></td>SprocketPro 200
<td></td>300
<td></td>100
<td></td>200
<td></td>SS158
</tr>
<tr>
<td></td>SocketSealer
<td></td>0
<td></td>n/a
<td colspan="2"></td>RM052
</tr>
<tr>
<td></td>Washers
<td rowspan="2"></td>32
<td></td>4
<td></td>28
<td></td>RM053
</tr>
<tr>
<td></td>25
<td></td>5
<td></td>20
<td></td>
</tr>
</tbody>
</table>
This should look like:
| Part number | Description | In stock | In shop | In warehouse |
|---|---|---|---|---|
| RM052 | SprocketPro 200 | 300 | 100 | 200 |
| SS158 | SocketSealer | 0 | n/a | |
| RM052 | Washers | 32 | 4 | 28 |
| RM053 | 25 | 5 | 20 | |
Notice that once you span a cell across a row or column, then you simply don't mention it in the following rows/columns. There are gaps in the example code above where you would expect a table cell.
Column groups are similar to the row groups (thead, tbody, and tfoot) in that they split your data grid into logical sections. The difference is that you define column groups any way you like. You can also set the rules="" attribute to only draw grid-lines around column groups. You can see an example of this in the common entities section of the HTML Reference page. And also in this slightly more simple example:
<table rules="groups" frame="border" border="1" summary="A
simple example of column groups and grouped grid-lines">An example table with column groups
<caption></caption>Description
<colgroup>
<col width="25%">
</colgroup>
<colgroup>
<col align="center" span="3" width="25%">
</colgroup>
<thead>
<tr><th rowspan="2"></th><th colspan="3">Size</th></tr>Width
<tr><th></th><th>Height</th><th>Depth</th></tr>SprocketPro
</thead>
<tbody>
<tr><td></td> <td>110mm</td>150mm
<td></td> <td>50mm</td></tr>GruntMaster
<tr><td></td> <td>890mm</td>400mm
<td></td> <td>500mm</td></tr>
</tbody>
</table>
Which looks like:
| Description | Size | ||
|---|---|---|---|
| Width | Height | Depth | |
| SprocketPro | 110mm | 150mm | 50mm |
| GruntMaster | 890mm | 400mm | 500mm |
There's another new tag in the example above: <caption>.
Its purpose is much the same as the summary="" attribute, except that table
captions are
displayed on visual browsers such as Netscape and Internet Explorer. If you
include a caption, it has to be the first tag after <table>.
Specifying columns and column groups has several advantages, though as stated
above, both column definitions and the row group tags (<thead>, <tbody>,
and <tfoot>) are strictly optional. First, setting widths
in both the the table tag and its columns allows large tables to be drawn
on-screen before all the data it contains has downloaded. This makes displaying
large data-grids quite a bit faster, though the difference in small tables
is less noticable. Secondly, specifying an align="" attribute
on a <col> tag carries that alignment onto every cell
in that column, which saves you from typing <td align="center"> for
every cell. Finally, you can set a class or id on a column or column group
and apply a CSS style to it. Strangely, Gecko-based browsers (i.e., Mozilla,
Netscape 6 and 7, Camino, Phoenix, etc) do not support most of what is stated
above, but currently these browsers make up about 5% of the market and once
the
programmers work out their philosophical issues, they'll catch up to Internet
Explorer 6 and Opera 7. You can see an example of that in the common
entities section of the HTML reference (the two centre columns should have a pale
blue background).
Table HTML Reference
This is the list of all table-related tags, and their most common attributes. In addition to those shown, any tag (at all) can have the following attributes: class="", title="", id="" and lang="".
| Can contain | Attribute | Description |
|---|---|---|
Table container tag: <table> |
||
|
frame="" | Specifies whether (and what type) a border should be drawn around the
table. Values are:
|
| border="" | Specifies the width of the border in pixels. If you don't also specify a frame attribute, the border is drawn around all four sides, and if you don't specify a rules attribute, setting a border implies the "all" value. | |
| rules="" | Specifies which kind of grid-lines to draw inside the table. Values are:
|
|
| summary="" | A brief description of the purpose and structure of the data grid for non-visual browsers. Consider this a required attribute. | |
| width="" | The width in pixels, or percent (if followed by the % sign) of the entire table. The height will adjust to fit the content. | |
| cellspacing="" cellpadding="" |
The values of these specify (respectively, in pixels) the space between cells, and the space inside each cell before the content starts. | |
Row groups: <thead>, <tbody>, <tfoot> |
||
<tr> |
align="" | One of left, center, right, or justify. The fifth value, char is not supported by any popular browser. All cells in the row group will acquire this setting for the horizontal alignment of its content, unless it is specified elsewhere (i.e., on the table row or cell itself). |
| valign="" | Specifies the vertical alignment of the content in each cells if the cell is larger than the content. One of top, middle or bottom. | |
Column-groups: <colgroup> |
||
<col> |
span="" | Specifies the number of columns in the group. This is actually optional,
but if all columns in the group are the same, you can use this instead
of entering a <col> element inside.The <colgroup> tag does not need to be closed (with </colgroup>)
unless it contains <col> tags. |
| width="" | Width in pixels (or percent of the table width, if a % symbol is added
to the end) of each of the columns in the group, unless a <col> tag
states otherwise. |
|
| align="", valign="" | As defined above, these attributes position the content within each cell, both horizontally and vertically. | |
Columns: <col> |
||
| n/a | span="" | The <col> tag has no closing tag, like <br>.
Span specifies that the attributes apply to multiple columns. A value
of 1 means "just the current column", and anything over that is the number
of columns to affect. |
| width="" | Specifies the width in pixels, or percent (with a % symbol on the end) of the table width, of the column(s). | |
| align="", valign="" | These attributes position the content within each cell, both horizontally and vertically. | |
Rows: <tr> |
||
<td>, <th> |
align="", valign="" | These attributes position the content within each cell, both horizontally and vertically. |
Cells and headers: <td>, <th> |
||
| Any block or inline element | rowspan="" colspan="" |
Number of rows or columns the cell takes up in the grid. The default of both these is 1 (which is to say, don't span) |
| align="", valign="" | These attributes position the content within each cell, both horizontally and vertically. | |
Table Caption: <caption> |
||
| n/a | none | If present, this tag must be written immediately after the <table> tag (not in a row or row-group etc.) This tag specifies a visible description of the table's subject. This is generally shorter than the summary="" attribute on the table tag because people can see the structure of the table from the header tags. |
Coding tricks
Regional variation
Using the same style-sheet on every page of your site ensures consistency,
but too much consistency (while reassuring) can get boring. You can use the id="" attribute
on the <body> tag
to apply different styles to different pages using the same style-sheet -
use the same id on pages in the same group or category to colour-code them.
Coping with obsolete browsers
At the time of writing, Netscape 4 has about 1% of the market, but of course this varies with your target audience. Big business corporations have to be able to trust their software, so it can take several years before they roll out an upgrade. There are several tricks available to cope with Netscape 4 while still using modern code and design. The easiest way of producing a readable page is to stop Netscape 4 from loading the stylesheet at all. This is the expedient and "I care enough to let you read the content" method, and for the most part it suffices. Better, after all, to provide content than to block users completely. However users of Netscape 4 may not understand why your site looks so unimpressive. Wired News' answer is to write a disclaimer and then hide it with a style-sheet rule so that it only appears when the style-sheet fails to load.
There are several ways to prevent Netscape 4 from loading or reading a style-sheet.
Most of these exploit bugs in Netscape software, which makes them feel a
bit "kludgy" to some. Others target the browser's unique name (called a User-Agent
header), which is sent with every request, and return a different style-sheet.
The method you choose is up to you. Browser "sniffing" as it is called, is
much more prone to errors, but is the more "honest" method of catching Netscape
4 users, while the kludges have the advantage of not using server time, as
well as being fairly simple. If you are experienced with scripting and web-servers,
you probably aren't following this tutorial. For the rest of us, any of the
following methods will work. Remember that you can load multiple style-sheets,
so you can load a very simple sheet with rules that Netscape 4 understands,
and then overwrite them with a style-sheet that Netscape 4 cannot read. Remember
that you can include tags such as hard rules (<hr>) to
break up content for older browsers, and then use CSS to hide those tags
(using display: none; ).
Method 1: the @import rule
This method exploits the fact that Netscape 4 doesn't support the @import rule, which inserts the contents of another style-sheet into the current.
Instead of linking directly to your style-sheet with the <link> tag, link
to a second file which contains simply:
@import url(stylesheetName.css);
Method 2: the odd-comment
Netscape 4 has a curious bug that stumbles over a very particular sequence of keystrokes. Once it trips up, it ignores all CSS rules until the next comment. You can use this to hide specific rules, or a whole style-sheet. For example:
body { background-color: black; color: white; }
/* Hide some code from Netscape 4 /*
/*/*/
body { background-color: white; color: black; }
/* End of hidden section */
In the above section, all browsers read the first line, but only Netscape 4 is prevented from reading the second rule which replaces it. That is, every visual browser except Netscape 4 shows black text on a white background.
A disclaimer
If you use a kludge like the ones above to stop Netscape 4 from loading a style-sheet, insert something like the following at the beginning of your documents to let them know. This also applies to other browsers that fail to load the style-sheet for whatever reason.
<div id="CSSWarning">If you can see this
message, then stylesheets are
disabled, unloaded, or not properly supported by your browser and therefore
the page cannot be laid out according to the designer's wishes. If you
are
using Netscape 4, then you should consider upgrading to a modern browser
such as one of the following. These are the author's favourites, not
necessarily the best available browsers:Mac OS
<ul><li><b></b>: <a href="http://www.apple.com/safari/">Safari</a>, Internet
Explorer
<a
href="http://microsoft.com/windows/ie/"></a>,
or <a href="http://www.mozilla.org/projects/chimera/">Chimera</a></li>Windows
<li><b></b>: <a href="http://www.mozilla.org/projects/phoenix/">Phoenix</a>,Internet
Explorer 6
<a
href="http://microsoft.com/windows/ie/"></a>,Opera 7
<a
href="http://www.opera.com/"></a></li>Linux
<li><b></b>: <a href="http://www.mozilla.org/projects/phoenix/">Phoenix</a>,Konqueror
<a
href="http://www.konqueror.org/"></a>, Mozilla
<a
href="http://www.mozilla.org/"></a></li>
</ul>
</div>
Then in your style-sheet, add the following rule:
@media all { { display: none; speak:
none; }
#CSSWarning
}
The second part is important and applies only to aural browsers such as JAWS or Dolphin HAL, text-to-speech packages for the visually impaired. It ensures that they do not have to listen to the warning over and over though it doesn't apply to them.
Meta tags and search engines
Most search engines no longer use keywords or site descriptions, so they aren't explained here. Prior to HTML 4, the <meta> tag was used to give miscellaneous information as well as faked HTTP header commands (an example of which is the Content-Type header you give in every document). That information included the name and contact details of the author, the name of the program that generated the content (e.g., Microsoft Front Page), and finally a page description and a series of keywords that summarised the content. This was picked up by early search engines and used to categorise information. Today, the most popular search engine doesn't show page descriptions —choosing instead to show excerpts from the document that match the search terms —and gives no special significance to meta-keywords, which were being abused by porn sites and thus making searches much less effective.
Today, Google assigns higher importance to pages which are linked to by many other pages, particularly if the search terms are given in the link text. That is, if four hundred people link to your site with the word "Sprockets" in the text of the link, then your site will appear very high up on the list when someone searches for sprockets. Not all of Google's ranking system is known: it's proprietary and besides, if unscrupulous marketers figure out the system, they can exploit it, which makes it less effective. It does pay more attention to text the higher up the page it is, which is another good reason to place your navigation after your main content in your code, then reposition it with style-sheets.
Google's way of ranking search results, should encourage you to use appropriate text in links. Linking around your site with images, or phrases like "click here" isn't just bad for the disabled!
![Click for larger version of this illustration [Illustration of column and row spanning]](images/tablespanning.png)