Unobtrusive and accessible form input labeling with jQuery

It's common practice to skip the use of



<form>
  <input type="text" value="Search this site" onfocus="this.value=''" />
  <input type="submit" value="Go"/>
</form>

This method is great for displaying simple forms in tight spaces, but accessibility suffers if you're not using label elements. The input's default label value is usually not restored if the input loses focus without being submitted.

jQuery makes it easy to maintain accessibility and graceful degradation with these types of forms. Let's start with an accessible form.

<form id="search_form">
  <fieldset>
    <label for="search_term">Search this site</label>
    <input name="search_term" id="search_term" type="text" />
    <input value="Go" type="submit" />
  </fieldset>
</form>

Here's the CSS

fieldset {
  border: none;
  width: 300px;
}
#search_form input {
  display: inline;
}
#search_form input[type="text"] {
  width: 10em;
}
#search_form legend,
#search_form label {
  display: none;
}

And here's the jQuery script.

// Declare short form elements in this page
// Add as many form id's as you need to the array
var shortForms = new Array(
  "#search_form"
);

// When the document's loaded, initialize short forms
$("document").ready(function() {
  handleShortFormEvent(shortForms);
});

/**
 * Handle initialization of all short forms
 *
 * @param array shortForms Array of short form IDs
 */

function handleShortFormEvent(shortForms) {
  for (var i in shortForms) {      
    shortFormInit(shortForms[i]);
  }
}

/**
 * Initialize a short form. Short forms may contain only one text input.
 *
 * @param string formID The form's ID, including #
 */

function shortFormInit(formID) {
  // Get the input ID and it's label text
  var labelValue = $(formID + " input[type='text']:first").siblings("label").html();
  var inputID = "#" + $(formID + " input[type='text']:first").attr("id");
 
  // Set the input value equal to label text
  $(inputID).val(labelValue);
 
  // Attach event listeners to the input
  $(inputID).bind("focus blur", function(e){
    var eLabelVal = $(this).siblings("label").html();
    var eInputVal = $(this).val();
   
    // Empty input value if it equals it's label
    if (eLabelVal == eInputVal) {
        $(this).val("");
    // Reset the input value if it's empty
    } else if ($(this).val() == "") {
      $(this).val(eLabelVal);
    }
  });
}

Here's what's happening above.

  1. An array of the page's short form IDs is set.
  2. In jQuery style, when the document's ready, initialize the short forms with handleShortFormEvent().
  3. handleShortFormEvent() loops through the forms and passes each off to shortFormInit().
  4. shortFormInit() sets text input values equal to its label. Then it attaches an event listener to each input which:
    • clears the default input value when someone focuses on it
    • restores the default input value if nothing was entered
    • retains any user values entered

I kept the handleShortFormEvent() and shortFormInit() functions separate to allow for initilization for form's loaded into the DOM after page load. I'd handle these instances with the help of jQuery.listen or the jQuery Live Query plugin.

It shouldn't be too difficult to expand this to handle multi-input forms but I believe there are jQuery plugins out there that do this.

Check out a working example.

Comments

Great example but I think

Great example but I think you may have an accessibility problem cause the label is not always visible. Generally that's not a problem since it disappear after you've filled the field. But what if you have an error on your form and want to check back what field is for?
For me, it would have been better to leave the original label and add an other sentence to precise it, or an example of accepted values. I would also set the color of the field text to a light grey at the beginning and change it back to black.

Like your blog by the way.

Add a title attribute with additional info

Typically I wouldn't use this technique on fields that employ validation. I suppose there is a chance that a user may miss the the field text if they click into it before reading its label. I'm not too worried about this, but a more meaningful submit button value would probably help reduce confusion (i.e. "Search" instead of "Go"). A title attribute could be added to the input field to display additional information about the field's purpose on hover.

Thanks for text color suggestion.

input[type="text"] {
color: #666;
}
input[type="text"]:focus {
color: #000;
}

I realize that these attribute selectors wouldn't work in IE 6, but it seems silly to use jQuery to address this.

what about password type

what about password type input?

Wouldn't use this for login forms

I hadn't consider login forms when I wrote this originally, but I don't think I'd use this technique for them. I'd list the labels for login and password fields normally.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <codeblock> <blockquote> <h1> <h2> <h3> <h4> <h5> <img>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. PHP source code can also be enclosed in <?php ... ?> or <% ... %>.
  • You may link to webpages through the weblinks registry
  • Twitter-style @usersnames are linked to their Twitter account pages.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
copyright © 2009, 2 tablespoons