a weblog
by jordan hollinger
Unobtrusive in-field text labels
In HTML user-input forms, it is not uncommon to see text fields with “labels” as grayed-out text in the field itself which disappear when clicked. Unfortunately, it’s harder than it should be.
My search for “best practices” on this technique left me…wanting. Firstly, I wasn’t sure what to call it. Secondly, many implementations were riddled with problems, paramount of which was abominable degradation. I am no accessibility expert, but these solutions didn’t even try. After just a little thought, I came up with something better than any of them. (Not to say it’s the best, but I can’t find one better.) My goals were:
- Unobtrusive
- Graceful degradation (screen-readers and non-JS browsers can fall back on the labels or title attributes)
- Uses all field attributes for their intended purposes
- Places all responsibility/logic in one location, removing the need for controllers to treat certain values or fields specially
A possible draw-back is that users cannot submit a value that matches the field’s title. If that’s a real problem, you could probably add some more checks to hack around it. But how often is someone’s first name First?
My implementation uses >= jQuery 1.3. Since we’re on the Web anyway, I thought I’d throw in a working example below:
The HTML
<form id="form_field_label_example" action="" method="post">
<p>
<label for="first_name">First</label>
<input id="first_name" name="first" title="First" type="text" />
<label for="middle_name">Middle</label>
<input id="middle_name" name="middle" title="Middle" type="text" />
<label for="last">Last</label>
<input id="last" name="last" title="Last" type="text" />
</p>
</form>
The JavaScript
<script type="text/javascript">
$(function() {
auto_label("form#form_field_label_example input[title][type=text]")
})
function auto_label(str) {
$(str).each(function() {
// Hide the field's real label
$('label[for=' + this.id + ']').hide()
// Set the label text and color for blank fields
if ( !this.value || this.value == this.title ) {
this.value = this.title
$(this).css('color', '#999')
}
// On focus of blank fields, clear the label text and reset the color
$(this).focus(function() {
if ( this.value == this.title ) {
this.value = ''
$(this).css('color', 'inherit')
}
})
// On unfocus of blank fields, restore the label text and color
$(this).blur(function() {
if ( !this.value ) {
this.value = this.title
$(this).css('color', '#999')
}
})
})
// Clear label text when submitting form
$(str).closest('form').submit(function() {
$(str).each(function() {
if ( this.title && this.value == this.title ) { this.value = '' }
})
})
}
</script>
