A Tale of Two Forms (Part 1)

A few weeks ago, my co-workers asked me to demonstrate how to convert a form built using HTML table elements into a more meaningful form structured with semantic HTML. Given the accessibility issues that affect table-based forms, I was more than happy to oblige.

Just to be clear, I don’t think that “tables are evil.” I actually feel quite the opposite. Tables have their place—they are absolutely fantastic for marking up tabular data like train schedules, stock quotes, spreadsheets and etceteras (which is what they were actually intended for.)

However, given their inherent grid-like structure, tables are sometimes used to lend a scaffolding to other elements like forms and divs that are inherently unstructured. Using tables in this way is an abuse and runs counter to the widely accepted notion that we, as web designers and developers, should strive to isolate our structural (HTML), presentational (CSS), and behavioral (JS) components.

Why Tables Are Inappropriate For Forms

Using tables to mark up forms is inappropriate for a few reasons:

  1. Marking up forms with tables adds unnecessary markup and decreases maintainability.

  2. Inserting form elements like labels and inputs in separate table cells erodes the fundamental relationships otherwise defined by their proximity to one another. This prevents users who rely on screen readers or other assistive devices from efficiently navigating your form.

  3. Tables are devices intended for information output, while forms are intended form information input.This is a fundamental inconsistency.
An example of a table-based form, which is what not to do.
An example of a table-based form, which is what not to do.

The HTML source for the table based form:

 1 <form action="" method="">
 2   <table>
 3     <tbody>
 4       <tr>
 5         <td><label for="first-name">First name</label></td>
 6         <td><input id="first-name" name="first-name" type="text"></td>
 7       </tr>
 8       <tr>
 9         <td><label for="last-name">Last name</label></td> 
10         <td><input id="last-name" name="last-name" type="text"></td>
11       </tr>
12       <tr>
13         <td><label for="phone-number">Phone Number</label></td>
14         <td><input id="phone-number" name="phone-number" type="text"></td>
15       </tr>
16       <tr>
17         <td><label for="email">Email</label></td>
18         <td><input id="email" name="email" type="text"></td>
19       </tr>
20       <tr>
21         <td><label for="address-1">Address Line 1</label></td>
22         <td><input id="address-1" name="address-1" type="text"></td>
23       </tr>
24       <tr>
25         <td><label for="address-2">Address Line 2</label></td>
26         <td><input id="address-2" name="address-2" type="text"></td>
27       </tr>
28       <tr>
29         <td><label for="city">City</label></td>
30         <td><input id="city" name="city" type="text"></td>
31       </tr>
32       <tr>
33         <td><label for="state">State</label></td>
34         <td><input id="state" name="state" type="text"></td>
35       </tr>
36       <tr>
37         <td><label for="zip-code">Zip Code</label></td>
38         <td><input id="zip-code" name="zip-code" type="text"></td>
39       </tr>
40       <tr>
41         <td></td> 
42         <td><input type="submit" value="submit"></td>
43       </tr>
44     </tbody>
45   </table>
46 </form>

The CSS for the table based form:

 1 body { background: #fff; font-family:sans-serif; }
 3 form { margin:50px auto; width:300px; }
 5 label { display:inline-block; text-transform: capitalize; width:145px; }
 7 input[type="text"] { width: 150px; }
 9 table {  border-spacing:0; border-collapse: collapse; width:300px; }
11 td { padding: 5px 0; }

Why You Should Build A More Semantic Form

There are several HTML elements that are specifically intended for use inside of forms and you should always make it a point to use them. Some of these elements include: divs, labels, and inputs. Here are a couple advantages of using them:

  1. Labels and inputs have an explicit, meaningful relationship. Placing these elements next to each other in your form will help to better convey the meaning of your document to web crawlers, screen readers and other assistive devices.

  2. Using divs to group related items (i.e. labels and inputs) will cutdown on the amount of code needed to markup a form. What’s more, divs were expressly intended to group related content and using them in appropriate fashion will improve the semantics of your document which, in turn, improves your SEO.

  3. By applying CSS intelligently, you can use these elements to construct a form that can take almost any shape—with less code. Furthermore, by separating structure from presentation, you can make your form more maintainable so changes to your layout merely require an adjustment to your CSS (rather than an adjustment to your CSS and your HTML).
An example of a more semantic form (notice how similar it is to the form above?)
An example of a more semantic form (notice how similar it is to the form above?)

The HTML for a more semantic form:

 1 <form action="" method="">
 2   <div>
 3     <label for="first-name">First name</label></td>
 4     <input id="first-name" name="first-name" type="text">
 5   </div>
 6   <div>
 7     <label for="last-name">Last name</label>
 8     <input id="last-name" name="last-name" type="text">
 9   </div>
10   <div>
11     <label for="phone-number">Phone Number</label>
12     <input id="phone-number" name="phone-number" type="text">
13   </div>
14   <div>
15     <label for="email">Email</label>
16     <input id="email" name="email" type="text">
17   </div>
18   <div>
19     <label for="address-1">Address Line 1</label>
20     <input id="address-1" name="address-1" type="text">
21   </div>
22   <div>
23     <label for="address-2">Address Line 2</label>
24     <input id="address-2" name="address-2" type="text">
25   </div> 
26   <div>
27     <label for="city">City</label>
28     <input id="city" name="city" type="text">
29   </div>
30   <div>
31     <label for="state">State</label>
32     <input id="state" name="state" type="text">
33   </div>
34   <div>
35     <label for="zip-code">Zip Code</label>
36     <input id="zip-code" name="zip-code" type="text">
37   </div>
38     <input type="submit" value="submit">
39 </form>

The CSS for a more semantic form:

 1 body { background: #fff; font-family: sans-serif; }
 3 form { margin: 50px auto; width: 300px; }
 5 div { display: inline-block; padding: 5px 0; width: 300px; }
 7 label { text-align: middle; text-transform: capitalize; width: 150px; }
 9 input[type="text"] { float: right; width: 150px; }
11 input[type="submit"] { margin-left: 145px; }

To Be Continued…

In Part 2, we’ll explore a few additional attributes and elements you can add to your forms in order to make them even more meaningful, accessible, and user friendly.