HTML5 Form Tutorial

In part one of this four five part tutorial, we’re going to create a contact form using the new HTML5 input attributes.  It must be stated outright that as browser support is still lacking for these attributes, this tutorial is for illustrative purposes only – I wouldn’t recommend using the new input types in a production environment yet.  That being said, it’s interesting to know what’s in store for us just around the corner.  Let’s get started.

HTML Template

This is the base template we’re going to use for the form.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>Contact Form</title>
</head>
<body>
</body>
</html>

As you can see, we’re using the HTML5 doctype.  Notice that the meta tag defining the character set is shorter than in previous versions of the language:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

In HTML5, the http-equiv and content attributes are superfluous, so we can strip those out.  The same goes for the type attribute in the style and script tags – we no longer need to define the type as text/javascript or text/css, as it’s implied by the tag name.

Input Types

Horse and PloughThe input element, as specified in HTML4, has ten values for it’s type attribute: button, checkbox, file, hidden, image, password, radio, reset, submit, and text.  The text input in particular has become the work-horse of HTML forms, used to capture a wide range of alphanumeric data.  This will change with the adoption of the new HTML5 input types.  In the same way that div is set to be superceded by header, nav, article, section, aside, and footer, the text attribute will be displaced by more semantic type attributes (search, tel, url, email, datetime, date, month, week, time, datetime-local, number, color and range) that accurately describe the data to be entered into them.

Contact Form

The form we’re going to create will not be a run-of-the-mill contact form, it will be aimed at satisfying the needs of a freelancer.  It’s purpose will be to collect enquiries from clients regarding potential projects – this enables us to examine how these new input types might work in a real-world setting.

The data our form will capture is as follows (the input type we will use is in brackets):

  • Name (text)
  • Company (text)
  • Email (email)
  • Telephone (tel)
  • Website (url)
  • Type of Project (select)
  • Projected Completion Date (date)
  • Estimated Budget (number)
  • Additional Details (textarea)
  • Please contact me by Email | Phone (radio)
  • Best time to contact? (time, disabled unless ‘contact by phone’ selected)

We’re going to seperate these properties into 3 fieldsets to make the form a little easier on the eye, and create the label and inputs for them.  The markup will look like this:

<form>
  <fieldset>
    <p><label>Name</label><input type="text" /></p>
    <p><label>Company</label><input type="text" /></p>
    <p><label>Email</label><input type="email" /></p>
    <p><label>Telephone</label><input type="tel" /></p>
    <p><label>Website</label><input type="url" /></p>
  </fieldset>
  <fieldset>
    <p><label>Type of Project</label></p>
    <p>
      <select>
        <option>HTML/CSS Build</option>
        <option>Custom jQuery Plugin</option>
        <option>Wordpress Template</option>
        <option>Other</option>
      </select>
    </p>
    <p><label>Projected Completion Date</label><input type="date" /></p>
    <p><label>Estimated Budget (&pound;)</label><input type="number" /></p>
    <p><label>Additional Details</label><textarea rows="5"></textarea></p>
  </fieldset>
  <fieldset>
    <p class="contact-method">
      <span>Please contact me by&hellip;</span>
      <label><input type="radio" value="Phone" checked="checked" /> Phone</label>
      <label><input type="radio" value="Email" /> Email</label>
    </p>
    <p><label>Best time to contact?</label><input type="time" /></p>
    <p><input class="submit" type="submit" name="submit" /></p>
  </fieldset>
</form>

Notice that we’ve added a class to the submit button and to the paragraph containing the contact method.  In an ideal world we’d be able to use a pseudo class like nth-child to style these elements, but it isn’t supported in IE6&7, so we’ll stick with normal classes for now.  We’re going to add a bit of basic CSS, just to make the form look a little nicer for the time being.

* { margin: 0; padding: 0 }
form { width: 460px; padding: 20px; color: #333333; font-family: Verdana, Geneva, sans-serif; font-size: 12px; margin: 0 auto }
fieldset { border: 0; padding: 10px; margin-bottom: 10px; background: #F6F6F6 }
legend { padding: 5px 10px }
label, span { float: left; clear: left; display: block; width: 180px; padding-right: 20px; text-align: right }
input, textarea, select { float: left; width: 200px }
.submit { width: 100px; float: right; margin-right: 37px }
select { width: 202px }
p { overflow: hidden; margin-bottom: 10px }
.contact-method label { clear: none; width: auto }
.contact-method input { float: none; width: 20px }

We’ll revisit the CSS in the next part of this tutorial.

Form Accessibility

In it’s present state, the form isn’t very accessible to people using screen readers, so we’re going to make some improvements by adding a legend to the fieldset, adding input names IDs (correction 01/05/11: names for php enabled forms, IDs for accessible form controls.  With thanks to Nick :)), and associating the input with it’s counterpart label using the ‘for’ attribute.  A brief note – there is some debate between accessibility experts on whether it’s better to wrap the input with it’s label, rather than creating sibling elements.  I think it’s a matter of personal preference – using the ‘for’ attribute creates an explicit association between the two elements.

As this form is contained within a basic page, it’s not necessary to define tab indices; the flow of the page is pretty basic and should tab in the correct order.  However, if you’re working with more complex markup, other elements on the page may interfere with the flow of the document – in this situation it’s best practice to define tab indices to assist with navigation of the page.

Once the modifications are complete, the markup will look like this:

<form>
  <fieldset>
    <legend>Contact Details</legend>
    <p><label for="name">Name</label><input id="name" type="text" /></p>
    <p><label for="company">Company</label><input id="company" type="text" /></p>
    <p><label for="email">Email</label><input id="email" type="email" /></p>
    <p><label for="telephone">Telephone</label><input id="telephone" type="tel" /></p>
    <p><label for="website">Website</label><input id="website" type="url" /></p>
  </fieldset>
  <fieldset>
    <legend>Project Details</legend>
    <p>
      <label for="project-type">Type of Project</label>
      <select id="project-type">
        <option>HTML/CSS Build</option>
        <option>Custom jQuery Plugin</option>
        <option>Wordpress Template</option>
        <option>Other</option>
      </select>
    </p>
    <p><label for="completion-date">Projected Completion Date</label><input id="completion-date" type="date" /></p>
    <p><label for="project-budget">Estimated Budget (&pound;)</label><input id="project-budget" type="number" /></p>
    <p><label for="project-details">Additional Details</label><textarea id="project-details" rows="5"></textarea></p>
  </fieldset>
  <fieldset>
    <legend>Contact Preferences</legend>
    <p>
      <span>Please contact me by&hellip;</span>
      <label><input id="contact-method" type="radio" value="Phone" checked="checked" /> Phone</label>
      <label><input id="contact-method" type="radio" value="Email" /> Email</label>
    </p>
    <p><label for="contact-time">Best time to contact?</label><input id="contact-time" type="time" /></p>
    <p><input type="submit" id="submit" value="Submit Form" /></p>
  </fieldset>
</form>

View Demo

Next time, we’ll be looking at sprucing our form up a bit with CSS. Stay tuned.

Photo Credit: Trevor Dennis on Flickr