Replacing Tables With Style

In 2001, A List Apart published an article that showed how tables could be replaced with semantic mark up for forms and the like.

The style code looked something like this (representative sample abstracted from the article):

div.row { clear: both; padding-top: 10px; } div.row span.label { float: left; width: 100px; } div.row span.formw { float: right; width: 335px; }

And the HTML:

<div class="row"> <span class="label">Name:</span><span class="formw"><input type="text" size="25" /></span> </div>

This code works! But it's incorrect, because the span element is an inline element, and as such does not have width (or height.) In order to specify width, one must use a block-level element such as div.

An alternative approach

This code gives a similar output to the previously published version:

div.row { padding-top: 5px; clear: both; } div.left { float: left; width: 100px; text-align: left; } div.right { margin-left: 110px; }

And the HTML:

<div class="row"> <div class="left">Name:</div> <div class="right"><input type="text" size="25"></div> </div> <div class="row"> <div class="left">Password:</div> <div class="right"><input type="text" size="25"></div> </div> <div class="row"> <div class="left"></div> <!--empty DIV required to straighten layout in IE --> <div class="right"><input type="submit"></div> </div>

The overall presentation of the form on the page is as follows:

Name:
Password:

In modern browsers, this is the presentational format that users have come to expect of tables-based form structures, but semantically more correct (i.e. not using a table to present non-tabular data.)

Another approach

Another approach is to use the definition list element (dl) to create the structure for a form. List items within a definition list have two components, the term (dt) and the definition (dd), which lend themselves to creating a tabular visual structure on the page, with a little presentational help from CSS.

The standard HTML for a definition list:

<dl> <dt>Name:</dt> <dd><input type="text" size="25"></dd> <dt>Password:</dt> <dd><input type="text" size="25"></dd> <dt></dt> <dd><input type="submit"></dd> </dl>

And the CSS to make it look more like a traditional form:

dt { float: left; width: 100px; padding-top: 5px; min-height: 1px; /* required to give layout to empty elements */ } dd { margin-left: 110px; padding-top: 5px; }

Together, this code gives a structure as below:

Name:
Password:

With a little change in the CSS you can achieve a slightly different effect:

dl { margin: 0; padding: 20px; width: 300px; border: solid 1px #000; background-color: #f0f8ff; } dl:first-child { padding-top: 0; } dt { padding-top: 15px; min-height: 1px; font-weight: bold; text-transform: uppercase; } dd { padding-top: 5px; } dd input[type=text] { border: solid 1px #000; width: 100%; height: 15px; }
Name
Address
Town / City

A minor concern with this approach is that it is semantically incorrect. A form's elements do not strictly represent a collection of terms and definitions, although a field label and field input may be considered to have a similar relationship to each other, if you're that way inclined.

If it bothers you, you could consider an unordered list. It's a little more complex (each row or fieldset has to be a list within the overall form list structure) but it works!