Bringing a form up to date – accessible, usable, beautiful. Part 1: the (x)html
OK – so beautiful might be a bit of an overstatement. I’ve just been updating a shipping and billing address form that was probably written in the last century and updating it from a table-based layout to something more accessible and usable and with the css set so it should be possible to style it to be a bit more beautiful.
Below is a possible end-result with some stylisation added in:
The form is an e-commerce style shipping and billing information input form.
We want to record some shipping info:
- First Name
- Last Name
- Street Address 1
- Street Address 2
- City
- County
- Postcode
- Country
Our form also has the following requirements:
- must record the same fields for billing info which may or may not be the same as the shipping info.
- must record the email of the person filling the form
- confirm that they agree to the website’s terms and conditions.
- must be cross-browser compatible and accessible
- must validate to w3c guidelines for (x)html and css.
This means that in designing our form we are going to use:
- fieldsets – to group form elements
- legends – to describe our fieldsets
- labels – to describe our form fields
- tabindex – to aid usability so that users can easily tab to the relevant fields
- <ol> ordered lists – for ease of styling and some degree of semantic correctness (this is debatable – there are a number of ways we could do this)
- an image with appropriate alt text to indicate mandatory fields
Just by way of example as to how these things work we are splitting the form into a number of different fieldsets:
- Shipping Name – the first and last name of the person the items are shipped to
- Shipping Address – the address lines the items will be shipped to
- Billing Name – the first name and last name of the person to be billed
- Billing Address – the address lines of the person being billed
- Website terms and Submission – terms and conditions checkbox and clear and submit buttons
Step 1
We declare our form
<form name=”shippingForm” id=”shippingForm” method=”post” action=”checkout.php”>
Step 2
We create the shipping fields for the form according to the requirements we set out above:
<div id=”shipping-details”>
<h2>Shipping Details</h2>
<div id=”required-message”><img src=”required.png” /> indicates a required field</div>
<fieldset>
<legend>Shipping Name</legend>
<ol>
<li>
<label for=”shippingFirstName”>First Name<img src=”required.png” alt=”First Name is required” /></label>
<input name=”shippingFirstName” type=”text” id=”shippingFirstName” tabindex=”10″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingLastName”>Last Name<img src=”required.png” alt=”Last Name is required” /></label>
<input name=”shippingLastName” type=”text” id=”shippingLastName” tabindex=”20″ size=”32″ maxlength=”50″ />
</li>
</ol>
</fieldset>
<fieldset>
<legend>Shipping Address</legend>
<ol>
<li>
<label for=”shippingAddress1″>Address 1<img src=”required.png” alt=”Street Address 1 is required” /></label>
<input name=”shippingAddress1″ type=”text” id=”shippingAddress1″ tabindex=”30″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingAddress2″>Address 2</label>
<input name=”shippingAddress2″ type=”text” id=”shippingAddress2″ tabindex=”40″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingCity”>City<img src=”required.png” alt=”City is required” /></label>
<input name=”shippingCity” type=”text” id=”shippingCity” tabindex=”50″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingCounty”>County<img src=”required.png” alt=”County is required” /></label>
<input name=”shippingCounty” type=”text” id=”shippingCounty” tabindex=”60″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingPostcode”>Postcode<img src=”required.png” alt=”Postcode is required” /></label>
<input name=”shippingPostcode” type=”text” id=”shippingPostcode” tabindex=”70″ size=”10″ maxlength=”20″ />
</li>
<li>
<label for=”shippingCountry”>Country<img src=”required.png” alt=”Country is required” /></label>
<input name=”shippingCountry” type=”text” id=”shippingCountry” tabindex=”80″ size=”32″ maxlength=”50″ />
</li>
</ol>
</fieldset>
</div>
So there we have the shipping part of our form.
* note that the tabindex is in order – I’ve just incremented each one by 10 in case I’ve messed up and need to add another field in between the existing ones.
Step 3
Rather than create the billing fields longhand I copied this text into textpad and did a replace to replace the word shipping with the word billing – hey presto we instantly have our equivalent billing fields.
Step 4
We add our final fieldset including the terms and conditions checkbox and submit button.
<div id=”conditions”>
<fieldset>
<legend>Website Terms</legend>
<p>
<label for=”websiteTerms”>
<input name=”websiteTerms” id=”websiteTerms” value=”unchecked” tabindex=”180″ type=”checkbox” />
Confirm you have read this website’s terms and conditions by checking this box</label>
</p>
<p>
<input type=”image” src=”submit.gif” alt=”submit form details and continue” name=”Submit” id=”Submit” value=”Submit” tabindex=”190″ />
</p>
</fieldset>
</div>
Step 5
Close our form
</form>
Step 6
It is possible that our shipping and billing address and person will be the same so we also want to add a checkbox that our visitor can click that will use some javascript to copy the data entered into the shipping address fields over to the matching billing address fields.
We add this is above the billing details:
<label for=”copyShippingInfo”>Use same info for billing</label>
<input name=”copyShippingInfo” type=”checkbox” id=”copyShippingInfo” value=”checkbox” tabindex=”90″ />
Our html
Should look something like this:
<form name=”shippingForm” id=”shippingForm” method=”post” action=”checkout.php”>
<div id=”shipping-details”>
<h2>Shipping Details</h2>
<div id=”required-message”><img src=”required.png” alt=”this image indicates a field is required” /> indicates a required field</div>
<fieldset>
<legend>Shipping Name</legend>
<ol>
<li>
<label for=”shippingFirstName”>First Name<img src=”required.png” alt=”First Name is required” /></label>
<input name=”shippingFirstName” type=”text”id=”shippingFirstName” tabindex=”10″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingLastName”>Last Name<img src=”required.png” alt=”Last Name is required” /></label>
<input name=”shippingLastName” type=”text” id=”shippingLastName”tabindex=”20″ size=”32″ maxlength=”50″ />
</li>
</ol>
</fieldset>
<fieldset>
<legend>Shipping Address</legend>
<ol>
<li>
<label for=”shippingAddress1″>Address 1<img src=”required.png” alt=”Street Address 1″ /></label>
<input name=”shippingAddress1″ type=”text” id=”shippingAddress1″tabindex=”30″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingAddress2″>Address 2</label>
<input name=”shippingAddress2″ type=”text” id=”shippingAddress2″ tabindex=”40″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingCity”>City<img src=”required.png” alt=”City is required” /></label>
<input name=”shippingCity” type=”text” id=”shippingCity” tabindex=”50″size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingCounty”>County<img src=”required.png” alt=”County is required” /></label>
<input name=”shippingCounty” type=”text” id=”shippingCounty” tabindex=”60″size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”shippingPostcode”>Postcode<img src=”required.png” alt=”Postcode is required” /></label>
<input name=”shippingPostcode” type=”text” id=”shippingPostcode”tabindex=”70″ size=”10″ maxlength=”20″ />
</li>
<li>
<label for=”shippingCountry”>Country<img src=”required.png” alt=”Country is required” /></label>
<input name=”shippingCountry” type=”text” id=”shippingCountry”tabindex=”80″ size=”32″ maxlength=”50″ />
</li>
</ol>
</fieldset>
</div>
<div id=”billing-details”>
<h2>Billing Details</h2>
<label for=”copyShippingInfo”>Use same info for billing</label>
<input name=”copyShippingInfo” type=”checkbox” id=”copyShippingInfo” value=”checkbox” tabindex=”90″ />
<fieldset>
<legend>Billing Name</legend>
<ol>
<li>
<label for=”billingFirstName”>First Name<img src=”required.png” alt=”First Name is required” /></label>
<input name=”billingFirstName” type=”text”id=”billingFirstName” tabindex=”100″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”billingLastName”>Last Name<img src=”required.png” alt=”Last Name is required” /></label>
<input name=”billingLastName” type=”text” id=”billingLastName”tabindex=”110″ size=”32″ maxlength=”50″ />
</li>
</ol>
</fieldset>
<fieldset>
<legend>Billing Address</legend>
<ol>
<li>
<label for=”billingAddress1″>Address 1<img src=”required.png” alt=”Street Address 1 is required” /></label>
<input name=”billingAddress1″ type=”text” id=”billingAddress1″tabindex=”120″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”billingAddress2″>Address 2</label>
<input name=”billingAddress2″ type=”text” id=”billingAddress2″tabindex=”130″ size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”billingCity”>City<img src=”required.png” alt=”City is required” /></label>
<input name=”billingCity” type=”text” id=”billingCity” tabindex=”140″size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”billingCounty”>County<img src=”required.png” alt=”County is required” /></label>
<input name=”billingCounty” type=”text” id=”billingCounty” tabindex=”150″size=”32″ maxlength=”50″ />
</li>
<li>
<label for=”billingPostcode”>Postcode<img src=”required.png” alt=”Postcode is required” /></label>
<input name=”billingPostcode” type=”text” id=”billingPostcode”tabindex=”160″ size=”10″ maxlength=”20″ />
</li>
<li>
<label for=”billingCountry”>Country<img src=”required.png” alt=”Country is required” /></label>
<input name=”billingCountry” type=”text” id=”billingCountry”tabindex=”170″ size=”32″ maxlength=”50″ />
</li>
</ol>
</fieldset>
</div>
<div id=”conditions”>
<fieldset>
<legend>Website Terms</legend>
<p>
<label for=”websiteTerms”>
<input name=”websiteTerms” id=”websiteTerms”value=”unchecked” tabindex=”180″ type=”checkbox” />
Confirm you have read this website’s terms and conditions by checking this box</label>
</p>
<p>
<input type=”image” src=”submit.gif” alt=”submit form details and continue” name=”Submit” id=”Submit” value=”Submit” tabindex=”190″ />
</p>
</fieldset>
</div>
</form>
End Result
Here is our unstyled form – as yet it lacks any css or javascript. In the next post we’ll look at adding CSS to make it look drastically different.
So far we’ve created the html and catered for accessibility elements in the form – is there anything I’ve missed? Could some of this have been done in a better way?

April 15, 2011 









this post is very usefull thx!
quite useful knowledge i have got from this article