Complex forms with CSS can be quite difficult to stylize because of the many existing discrepancies across browsers. Let's say that we want to stylize a form for ordering books. We could start with a markup like this:
<div id="order">
<h2>Order your books</h2>
<form action="#" method="post">
<table summary="Order: copies, code, title, price">
<tr>
<th scope="col">Copies</th>
<th scope="col">Code</th>
<th scope="col">Title</th>
<th scope="col">Price</th>
</tr>
<tr>
<td><input type="text" name="copy1" id="copy1" /></td>
<td><input type="text" name="code1" id="code1" /></td>
<td><input type="text" name="title1" id="title1" /></td>
<td><input type="text" name="price1" id="price1" /></td>
</tr>
<tr>
<td><input type="text" name="copy2" id="copy2" /></td>
<td><input type="text" name="code2" id="code2" /></td>
<td><input type="text" name="title2" id="title2" /></td>
<td><input type="text" name="price2" id="price2" /></td>
</tr>
<tr>
<td><input type="text" name="copy3" id="copy3" /></td>
<td><input type="text" name="code3" id="code3" /></td>
<td><input type="text" name="title3" id="title3" /></td>
<td><input type="text" name="price3" id="price3" /></td>
</tr>
<tr>
<td><input type="text" name="copy4" id="copy4" /></td>
<td><input type="text" name="code4" id="code4" /></td>
<td><input type="text" name="title4" id="title4" /></td>
<td><input type="text" name="price4" id="price4" /></td>
</tr>
</table>
<fieldset>
<legend>Payment method</legend>
<ul>
<li>
<label for="cod">COD</label>
<input type="checkbox" name="cod" id="cod" value="cod" />
</li>
<li>
<label for="visa">VISA</label>
<input type="checkbox" name="visa" id="visa" value="visa" />
</li>
<li>
<label for="american-express">American Express</label>
<input type="checkbox" name="american-express" id="american-express" value="american-express" />
</li>
<li>
<label for="master-card">Master Card</label>
<input type="checkbox" name="master-card" id="master-card" value="master-card" />
</li>
</ul>
<div class="footer">
<div class="left">
<label for="cc-number">N.</label>
<input type="text" name="cc-number" id="cc-number" />
</div>
<div class="right">
<label for="cc-expires">Expires</label>
<input type="text" name="cc-expires" id="cc-expires" />
</div>
</div>
</fieldset>
<ul class="customer-info">
<li>
<label for="name">Name</label>
<input type="text" name="name" id="name" />
<label for="address">Address</label>
<input type="text" name="address" id="address" />
</li>
<li>
<label for="city">City</label>
<input type="text" name="city" id="city" />
<label for="state">State</label>
<input type="text" name="state" id="state" />
</li>
<li>
<label for="phone">Phone</label>
<input type="text" name="phone" id="phone" />
<label for="email">Email</label>
<input type="text" name="email" id="email" />
</li>
</ul>
<p><input type="submit" name="submit" id="submit" value="Place order" /></p>
</form>
</div>
Why a table? It's quite simple to understand: in this form, data are organized in name/field pairs (name, title, price, etc.), so the most semantical way to mark up this is using a table. Of course not all data is contained within a table, so this is another issue to take into account. Here's our CSS styles:
/* General styles */
body, h2, form, fieldset, table, th, td, ul, p, legend {
margin: 0;
padding: 0;
border: none;
list-style: none;
color: #333;
}
body {
background: #fff;
color: #333;
font: 76% Arial, Helvetica, sans-serif;
}
h2 {
font-size: 1.6em;
font-weight: normal;
color: #666;
}
/* Give input elements a consistent dimension */
input {
font: 1em Arial, Helvetica, sans-serif;
}
/* Styling the main container */
#order {
width: 700px;
margin: 2em auto;
padding: 8px 6px;
}
/* Styling the form element just for IE6/7 */
form {
height: 100%; /* http://www.satzansatz.de/cssd/onhavinglayout.html */
}
/* Styling the main title */
h2 {
text-align: center;
text-transform: uppercase;
}
/* Styling the table for order details */
form table {
width: 100%;
padding: 6px 0;
border-spacing: 0;
border-collapse: collapse;
margin-bottom: 0.5em;
}
form table th {
text-align: left;
font-weight: normal;
}
form table td {
padding-bottom: 3px;
}
form table td input {
border: 1px solid #ccc;
display: block;
margin-right: 4px;
}
form table td #copy1,
form table td #copy2,
form table td #copy3,
form table td #copy4,
form table td #price1,
form table td #price2,
form table td #price3,
form table td #price4 {
width: 50px;
}
form table td #code1,
form table td #code2,
form table td #code3,
form table td #code4 {
width: 70px;
}
form table td #title1,
form table td #title2,
form table td #title3,
form table td #title4 {
width: 505px;
}
/* Payment method: fieldset and its children */
fieldset legend {
font-weight: bold;
padding-bottom: 5px;
}
fieldset ul {
width: 100%;
height: 100%;
overflow: hidden;
}
fieldset ul li {
float: left;
width: 172px;
margin: 0;
}
fieldset ul li label {
font-weight: bold;
vertical-align: middle;
}
fieldset ul li input {
vertical-align: middle;
}
fieldset div.footer {
width: 100%;
padding: 10px 0 20px 0;
height: 100%;
overflow: hidden;
}
fieldset div.footer div.left {
float: left;
width: 200px;
margin: 0;
}
fieldset div.footer div.right {
float: right;
width: 200px;
margin: 0;
position: relative;
left: 17px;
}
fieldset div.footer input {
vertical-align: middle;
border: none;
border-bottom: 1px solid #ccc;
}
fieldset div.footer label {
vertical-align: middle;
font-weight: bold;
}
/* Customer info */
form ul.customer-info {
width: 100%;
padding: 15px 0;
overflow: hidden;
height: 100%;
}
form ul.customer-info li {
float: left;
width: 340px;
margin: 0 4px 0 0;
}
form ul.customer-info input {
vertical-align: middle;
border: none;
border-bottom: 1px solid #ccc;
width: 110px;
margin-right: 5px;
}
form ul.customer-info label {
font-weight: bold;
vertical-align: middle;
padding-right: 4px;
}
/* Submit button */
form #submit {
border-color: #ccc;
background: #666;
font-weight: bold;
color: #fff;
}
The rendering of the fieldset
element is inconsistent in Internet Explorer 7 and lower, so we have to fix it using conditional comments:
<!--[if lt IE 8]>
<style type="text/css" media="screen">
fieldset legend {
position: relative;
left: -6px;
}
</style>
<![endif]-->
View the live demo
The secret here for achieving a good consistency across browsers is to explicitly specify a font size and family on form elements. By doing so, we can actually have proportional form elements that scale gracefully along text.