Creating Accessible Forms

Learn how to use fieldsets, legends, labels, tab order, and access keys to make your HTML forms more accessible and usable for your visitors.

In HTML forms we looked at the basics of creating HTML forms: GET vs POST, text fields, checkboxes, radio buttons and so on. In this tutorial we're going to go a step further and look at some of the ways you can make forms more accessible and usable for your visitors.

Web accessibility is important because it makes it easier for users to visit and use your site. This means happier visitors and more traffic!

We'll cover the following topics:

  • Using the fieldset and legend elements to group form fields in a logical way
  • Adding labels to form fields with the label element
  • Controlling the tabbing order of the elements in a form
  • Speeding up form access and improving accessibility through the use of access keys

By the end of this tutorial you'll be well on your way to designing wonderfully accessible forms. Read on...

Grouping form fields with fieldsets

In the past you've probably built, or at least seen, complex forms with many, many fields to fill in. (Shopping cart checkouts spring to mind.) If the fields are all bunched together on the page, the effect can be confusing for the visitor, if not downright overwhelming.

An accessible form groups fields together so the form makes more sense and is less intimidating. You can of course do this visually with whitespace, colours, or separator bars. However, HTML gives us a way to group fields at a structural level instead - the fieldset element. By grouping fields within fieldsets, you can not only visually group the areas of your form, but structurally group them too. This means that the browser knows which fields are grouped together - great for things such as screen readers, for instance.

Here's a simple example. Let's say we're building the proverbial shopping cart checkout form. We might group the form fields into fieldsets such as billing address, shipping address, and payment details, as follows:


<form action="">
  <fieldset>
    <legend>Billing details</legend>
    <p>Name: <input type="text" name="billingName"/></p>
    <p>Address: <input type="text" name="billingAddress"/></p>
    <p>Postal code: <input type="text" name="billingPostcode"/></p> 
    <p>Country: <select name="billingCountry"><option>Australia</option><option>Canada</option><option>New Zealand</option><option>United Kingdom</option><option>United States</option></select></p>
  </fieldset>
  <fieldset>
    <legend>Shipping details</legend>
    <p>Name: <input type="text" name="shippingName"/></p>
    <p>Address: <input type="text" name="shippingAddress"/></p>
    <p>Postal code: <input type="text" name="shippingPostcode"/></p> 
    <p>Country: <select name="shippingCountry"><option>Australia</option><option>Canada</option><option>New Zealand</option><option>United Kingdom</option><option>United States</option></select></p>
  </fieldset>
  <fieldset>
    <legend>Payment details</legend>
    <p>Card number: <input type="text" name="cardNumber"/></p>
    <p>CVV code: <input type="text" name="cvvCode"/></p>
    <p>Expiry date: <input type="text" name="expiryDate"/></p> 
  </fieldset>
  <div id="buttons">
    <input type="button" name="paymentButton" value="Make payment"/>
  </div>
</form>

Here's what the above form looks like:

Billing details

Name:

Address:

Postal code:

Country:

Shipping details

Name:

Address:

Postal code:

Country:

Payment details

Card number:

CVV code:

Expiry date:

Not the most attractive form admittedly, but you get the idea! (Don't worry, we smarten it up in the Styling forms with CSS tutorial.)

The <fieldset></fieldset> tags are used to group the fields into fieldsets. After each opening <fieldset> tag, a legend element is used to add a caption to the fieldset. This caption is not only useful as a visual indicator of the type of fields in the fieldset, but it's also very handy for people who are using non-visual browsers such as screen readers.

Improving accessible forms with field labels

In the above example, we've simply placed the field labels ("Name:", "Address:" and so on) before our fields in the markup. While this works, it also lacks any structural association between the field labels and the fields themselves. How is the browser supposed to know that "Address:" is the label for the billingAddress field, for example?

Luckily, HTML provides us with a way to structurally link field labels with the fields themselves: the label element. The basic syntax is:


<label for="fieldId">label text</label>
<input id="fieldId" ...

The label is associated with its field using for="fieldId" (so each field in the form needs to be given an ID).

Again, structural markup like this is great for people using screen readers. Rather than the screen reader just saying "Text field" for each field, it can now say "Billing name", for example.

Here's our above example rewritten using labels to link each label with its respective field:


<form action="">
  <fieldset>
    <legend>Billing details</legend>
    <p><label for="billingName">Name:</label> <input type="text" name="billingName" id="billingName"/></p>
    <p><label for="billingAddress">Address:</label> <input type="text" name="billingAddress" id="billingAddress"/></p>
    <p><label for="billingPostcode">Postal code:</label> <input type="text" name="billingPostcode" id="billingPostcode"/></p> 
    <p><label for="billingCountry">Country:</label> <select name="billingCountry" id="billingCountry"><option>Australia</option><option>Canada</option><option>New Zealand</option><option>United Kingdom</option><option>United States</option></select></p>
  </fieldset>
  <fieldset>
    <legend>Shipping details</legend>
    <p><label for="shippingName">Name:</label> <input type="text" name="shippingName" id="shippingName"/></p>
    <p><label for="shippingAddress">Address:</label> <input type="text" name="shippingAddress" id="shippingAddress"/></p>
    <p><label for="shippingPostcode">Postal code:</label> <input type="text" name="shippingPostcode" id="shippingPostcode"/></p> 
    <p><label for="shippingCountry">Country:</label> <select name="shippingCountry" id="shippingCountry"><option>Australia</option><option>Canada</option><option>New Zealand</option><option>United Kingdom</option><option>United States</option></select></p>
  </fieldset>
  <fieldset>
    <legend>Payment details</legend>
    <p><label for="cardNumber">Card number:</label> <input type="text" name="cardNumber" id="cardNumber"/></p>
    <p><label for="cvvCode">CVV code:</label> <input type="text" name="cvvCode" id="cvvCode"/></p>
    <p><label for="expiryDate">Expiry date:</label> <input type="text" name="expiryDate" id="expiryDate"/></p> 
  </fieldset>
  <div id="buttons">
    <input type="button" name="paymentButton" value="Make payment"/>
  </div>
</form>

And here's what it looks like. Notice that on most browsers you can click on the field labels to give focus to the fields themselves. This is particularly useful for those tiny checkbox and radio button fields!

Billing details

Shipping details

Payment details

Setting the tabbing order of form fields

As you probably know, with most browsers you can use the Tab key to move between the form controls and links in a page. Many people find this much quicker and easier than clicking on the page elements with their mouse (and of course many people don't even use mice!).

This is great, but sometimes the tabbing order goes awry. The browser determines the tabbing order by the order the elements are placed in the markup, which usually works OK. However, consider the following example with form fields in a table:


<form action="">
  <table style="width: 100%; border: none;">
    <tr>
      <td>Name:<br/><input type="text" name="billingName"/></td>
      <td>Postal code:<br/><input type="text" name="billingPostcode"/></td>
    </tr>
    <tr>
      <td>Address:<br/><input type="text" name="billingAddress"/></td>
      <td>Country:<br/><select name="billingCountry"><option>Australia</option><option>Canada</option><option>New Zealand</option><option>United Kingdom</option><option>United States</option></select></td>
    </tr>
  </table>
</form>

Here's how this form looks:

Name:
Postal code:
Address:
Country:

As a visitor you'd probably expect the tabbing order to be Name, Address, Postal code, then Country. If you try tabbing through the fields though, you'll see that the tabbing order is the order that they appear in the markup: Name, Postal code, Address, Country.

We can fix this with the tabindex attribute, like this:


<form action="">
  <table style="width: 100%; border: none;">
    <tr>
      <td>Name:<br/><input type="text" name="billingName" tabindex="1"/></td>
      <td>Postal code:<br/><input type="text" name="billingPostcode" tabindex="3"/></td>
    </tr>
    <tr>
      <td>Address:<br/><input type="text" name="billingAddress" tabindex="2"/></td>
      <td>Country:<br/><select name="billingCountry" tabindex="4"><option>Australia</option><option>Canada</option><option>New Zealand</option><option>United Kingdom</option><option>United States</option></select></td>
    </tr>
  </table>
</form>

Now the form fields are in the expected tab order - try tabbing through them:

Name:
Postal code:
Address:
Country:

Using access keys for quick keyboard access

To further improve accessibility for people who use the keyboard, you can assign access keys to your form elements. Visitors can then press Alt+accesskey (Windows browsers) / Control+accesskey (Mac browsers) to give focus to, or otherwise manipulate the element. The following HTML elements can have access keys assigned to them:

a (a link)
Generally follows the link when the access key is pressed.
area (an image map "hotspot" link)
Generally follows the link when the access key is pressed.
button (a form button)
Gives focus to the button, or on some browsers, "clicks" the button, when the access key is pressed.
input (a form input control)
For text input types: gives focus to the control when the access key is pressed. For all other input types: pressing the access key usually "clicks" on the control (e.g. checks/unchecks a checkbox or "clicks" a button).
legend (a fieldset legend)
Gives focus to the first form field in the fieldset associated with the legend when the access key is pressed.
object (a generic inclusion of an object, e.g. a Flash movie)
Generally gives focus to the object when the access key is pressed.
select (a drop-down menu)
Generally gives focus to the menu when the access key is pressed.
textarea (a multi-line text input control)
Generally gives focus to the textarea when the access key is pressed.

Be careful when choosing access keys, as they will often prevent browser menu options that use the same keyboard shortcut from working. For example, if you assign an access key of 'F' to a form field, Windows users will no longer be able to select the File menu with Alt+F while viewing your page. You'll need to decide for yourself which is more important: your form field or the menu option!

Indicating access keys

According to the W3C HTML specification, the browser should ideally indicate the access keys to the visitor somehow (e.g. by underlining the access key in the form label). In practice, hardly any browsers do this, so it's up to you to indicate the available access keys to your visitors. You could, for example, underline or bold the appropriate letter in the label text.

An example

Let's enhance our "form in a table" example above with access keys:


<form action="">
  <table style="width: 100%; border: none;">
    <tr>
      <td><span style="text-decoration: underline;">N</span>ame:<br/><input type="text" name="billingName" tabindex="1" accesskey="N"/></td>
      <td><span style="text-decoration: underline;">P</span>ostal code:<br/><input type="text" name="billingPostcode" tabindex="3" accesskey="P"/></td>
    </tr>
    <tr>
      <td><span style="text-decoration: underline;">A</span>ddress:<br/><input type="text" name="billingAddress" tabindex="2" accesskey="A"/></td>
      <td><span style="text-decoration: underline;">C</span>ountry:<br/><select name="billingCountry" tabindex="4" accesskey="C"><option>Australia</option><option>Canada</option><option>New Zealand</option><option>United Kingdom</option><option>United States</option></select></td>
    </tr>
  </table>
</form>

Here's how it looks. Try pressing the access keys (don't forget to use them with the Control or Alt keys as appropriate):

Name:
Postal code:
Address:
Country:

Accessible forms go a long way to making your site easy and enjoyable to use. By using one or more of the above techniques — fieldsets, legends, labels, tab order, and access keys — you can help to make your forms more accessible to your visitors.

Follow Elated

Related articles

Responses to this article

There are no responses yet.

Post a response

Want to add a comment, or ask a question about this article? Post a response.

To post responses you need to be a member. Not a member yet? Signing up is free, easy and only takes a minute. Sign up now.

Top of Page