Marking Up Forms
I've been looking for a good way to mark up forms for a long while now. As of right now, I still haven't found a way that's really satisfying. The way HTML is set up right now, marking up a form that degrades perfectly and still fits into that semanticness mould that people tend to squack about all the time is a little difficult.
Of course, it seems the easiest way to mark up a form and style it is with tables. The way most forms are laid out even gives the illusion that it is data that really should be in a table anyway. The purists among you will call it tabular data. That term is odd. Anyway. Here is the HTML for a form marked up as if it were a table.
Figure 1. A form marked up as a table
<fieldset>
<legend>Application for Dessert</legend>
<table>
<tfoot>
<tr>
<td colspan="2"><input type="submit" value="Apply for Dessert"></td>
</tr>
</tfoot>
<tbody>
<tr>
<td><label for="name">Your name:</label></td>
<td><input id="name" name="name" type="text" size="20"></td>
</tr>
<tr>
<td><label for="email">E-mail address:</label></td>
<td><input id="email" name="email" type="text" size="30"></td>
</tr>
<tr>
<td>Dessert type:</td>
<td>
<label><input name="type" value="pastry" type="radio"> Pastry</label>
<label><input name="type" value="cake" type="radio"> Cake</label>
<label><input name="type" value="fruit" type="radio"> Fruit</label>
</td>
</tr>
<tr>
<td colspan="2">
<label><input name="low_fat" type="checkbox">
Use Splenda with my dessert because I'm watching my waistline
</label>
</td>
</tr>
</tbody>
</table>
</fieldset>
Now this isn't too bad. If you stick some basic styling you can come up with a pleasing design that degrades well (see the example). There are a few problems though. The first being the semantics of the HTML involved. At first glance it makes sense to use a table right up until the checkbox field becomes involved. It gets even more complex if more text is required in the form. What happens if the form needs to be restyled? Either redo the HTML or make a giant mockery of the stylesheets with display: block this and display: table that.
The simple fact is that tables, while they seem perfect for this job, just aren't. Tables are designed for a matrix of data. A form is not. A form, at the best of times, is only a 1:1 relationship between a field and a label. That's not what a table is for.
However, there does seem to be an element that fits that description instead: the definition list. Of course!
Figure 2. A form marked up as a definition list
<fieldset>
<legend>Application for Dessert</legend>
<dl>
<dt><label for="name">Your name:</label></dt>
<dd><input id="name" name="name" type="text" size="20"></dd>
<dt><label for="email">E-mail address:</label></dt>
<dd><input id="email" name="email" type="text" size="30"></dd>
<dt>Dessert type:</dt>
<dd>
<label><input name="type" value="pastry" type="radio"> Pastry</label>
<label><input name="type" value="cake" type="radio"> Cake</label>
<label><input name="type" value="fruit" type="radio"> Fruit</label>
</dd>
<dd>
<label><input name="low_fat" type="checkbox">
Use Splenda with my dessert because I'm watching my waistline
</label>
</dt>
</dl>
<p><input type="submit" value="Apply for Dessert"></p>
</fieldset>
Again, it seems perfect. But it's not quite right. That checkbox just sticks out like a sore thumb. It doesn't really fit in with the dd, or the dt. Using the dd here just makes a little more sense because of the stylesheets we're using to make it look a little more like a table (see the second example). It still just isn't right.
Sometimes the answer is staring us in the face all along:
Figure 3. A form marked up with only the essentials
<fieldset>
<legend>Application for Dessert</legend>
<p>
<label for="name">Your name:</label>
<input id="name" name="name" type="text" size="20">
</p>
<p>
<label for="email">E-mail address:</label>
<input id="email" name="email" type="text" size="30">
</p>
<p class="radio">
<span class="label">Dessert type:</span>
<label><input name="type" value="pastry" type="radio"> Pastry</label>
<label><input name="type" value="cake" type="radio"> Cake</label>
<label><input name="type" value="fruit" type="radio"> Fruit</label>
</p>
<p class="checkbox">
<label><input name="low_fat" type="checkbox">
Use Splenda with my dessert because I'm watching my waistline
</label>
</p>
<p><input type="submit" value="Apply for Dessert"></p>
</fieldset>
Yes, that's right. Those are just paragraph tags. A div could also work, but paragraphs do fit this situation somewhat better. Because HTML has the label element, we really don't need any more markup than what's already there. At least not for a basic form like the example will show.
With the paragraph tag you don't worry about each field fitting some sort of norm so that it is in sync with all the other fields. Forms should be malleable. One size does not fit all with user inputted data. You see this trend all over the Internet... form fields all look the same just so that the form looks more uniform and orderly. But you can have a perfectly attractive form with some basic styles and form fields that are sized and positioned to fit the data entering them. It can also be a good visual cue for what kind of data you want in the field. A user name is typically shorter than an e-mail address for example.
The biggest downside is styling. Less markup means more work to make it fit properly. You'll notice I needed to put a span in and some classes so that the form didn't go all wonky on the labels for checkboxes and radio buttons. There's really not much that can be done about that.
All in all, I think this arrangement works the best. While it doesn't degrade without styles as well as a table or as a definition list, the form is still 100% usable. That's a compromise I'm willing to make for now I think.