Thursday, 12 June 2008

Simple FORMs are happy FORMs

Introduction

I spotted a nice tutorial about using jQuery to highlight fields and blocks of fields in forms over at Janko at Warp Speed this morning.

While the jQuery is spot on (gotta love the brevity / simplicity of jQuery), the form mark-up left a bit to be desired. I'm not picking on Janko here, you see this pattern repeated over the web.

Janko suggested the following markup:

<div class="row">
<div class="left">First name</div>
<div class="right"><input name="Text1" type="text" class="text" /></div>
<div class="clear"></div>
</div>

Clean Markup

There are few things that can be improved here:
  1. No labels. It is very important for people using assistive technologies (screen readers) that input elements (the text boxes) are associated with a label. Why? Close your eyes and tab about a web form. How do you know which field you are on? A label is tied to an input box and screen readers understand this association and can provide additional feedback to the user to help them orientate and navigate around a form.
  2. There's a lot of unnecessary
    's. Not really a big issue, but if they aren't needed, why put them in? It complicates your mark-up and, if you are paying for your bandwidth, why waste good money? Less mark-up also means your page loads faster too.

    Note: In the real world, you sometimes have to add semantically neutral mark-up to give you hooks to attach additional styles to or to work around various browser quirks, but in this case we can safely remove them.
  3. The clearing div. There are a number of techniques for avoiding this markup cruft. And in most cases, they can be removed completely.
Lets fix those issues and see what we end up with:

<div class='row'>
<label for='Text1'>First Name</label> <input id='Text1' name='Text1' type='text' />
</div>

Doesn't that look easier to understand?

Clean CSS

Now we have some clean markup, the CSS needed to style it becomes much cleaner too (I've left out the stuff that makes it pretty to keep things simple):

.row {
clear: both;
float: left;
width: 100%;
}
label {
float: left;
width: 150px;
cursor: pointer;
}

Let's look at those rules one at a time and explain what's going on:

.row {}

  • clear: both;
    We are using floats to achieve the desired layout. This ensures that each row appears underneath the one above instead of floating next to each other across the screen.
  • float: left;
    The row needs to fully contain its child elements (label, input). Without this, the row would collapse up into nothing and you would never see the background change when the input got focus (the whole point of Janko's post).
  • width: 100%;
    Floated elements will shrink to match their content. This makes sure that every row runs the full width of its container (usually a fieldset).
.row label {}
  • float: left;
    We want to label and the input elements to line up on the same row. Also, we want each of the input elements to line up vertically so we add a
  • width: 150px;
    to ensure that all the labels are the same width. Because we aren't floating the input elements, they automatically butt up next to the labels.
  • cursor: pointer;
    Not absolutely neccessary, but changing the cursor to the hyperlink (pointing finger) cursor indicates to a sited user that the label is clickable. If you click the label, most browsers will automatically switch focus to the linked input element (another very good reason to use labels).
Conclusion

I'm a big fan of the KISS principle: Keep It Simple, Stupid! Less code means less potential (programmer) errors, less work for the browser, lower bandwidth costs and increased readability. It's a win/win situation.

Go forth and simplify!

Zemanta Pixie