Easier autopopulating textboxes with JavaScript

Oct 18 2007

Roger Johannson just posted a rather lengthy script over at 456 Berea Street that is intended to help the accessibility-conscious developer combat their designer’s label-less form design. It struck me as a little silly to repeat the label as an unnecessary title attribute, so I wondered how easy it would be to use the existing label instead of futzing with the input value. As it turns out, it’s very easy—here’s how to do it.

(Note: This technique is similar to one covered in A List Apart last year, but uses the CSS z-index instead of hiding things.)

How it works

Here’s our form markup—I am using the technique favoured by Cameron Adams, where the label does not wrap the input, but appears before it in the markup:

  1. <form>
  2. <fieldset>
  3. <ol>
  4. <li>
  5. <label for="name">Your name</label>
  6. <input type="text" name="name" id="name" class="populate" />
  7. </li>
  8. <li>
  9. <label for="email">Your email address</label>
  10. <input type="text" name="email" id="email" class="populate" />
  11. </li>
  12. </ol>
  13. </fieldset>
  14. </form>
  15.  
  16. Download this code: /code/visibleform.txt

Add a little CSS – the important part is the setting of position: relative on the parent LI (so the absolute positioning works):

  1. li {
  2. position: relative;
  3. list-style: none;
  4. }
  5.  
  6. label {
  7. position: absolute;
  8. top: 4px;
  9. left: 3px;
  10. color: #999;
  11. }
  12.  
  13. Download this code: /code/visiblecss.txt

As the label text is already present, we simply position it over the top of the empty form element, and then hide it underneath the input when it is focused by setting the z-index to -1. When the input loses focus, we reset the z-index unless it has some content in:

  1. var VisibleLabel = {
  2. input_class: 'populate',
  3. inputs_to_populate: [],
  4. init: function () {
  5. if (!document.getElementById) return;
  6. var inputs = document.getElementsByTagName('input');
  7. for (var i=0,len=inputs.length; i<len; i++) {
  8. if (inputs[i].className == this.input_class) this.inputs_to_populate.push(inputs[i]);
  9. }
  10. for (var i=0,len=this.inputs_to_populate.length; i<len; i++) {
  11. this.inputs_to_populate[i].onfocus = function () {
  12. VisibleLabel.previousSibling(this).style.zIndex = '-1';
  13. }
  14. this.inputs_to_populate[i].onblur = function () {
  15. if (this.value == '') {
  16. VisibleLabel.previousSibling(this).style.zIndex = '0';
  17. }
  18. }
  19. }
  20. },
  21. previousSibling: function (el) {
  22. label = el.previousSibling;
  23. while (label.nodeName != 'LABEL') {
  24. label = label.previousSibling;
  25. }
  26. return label;
  27. }
  28. }
  29.  
  30. window.onload = function () {
  31. VisibleLabel.init();
  32. }
  33.  
  34. Download this code: /code/visiblelabel.txt

Substitute your own preferred event registration technique for the clunky DOM 0 methods, and you’re good to go.

View the simple demo page—try clicking into and out of the form elements to see the label text appear and disappear.

Filed under: Javascript, Accessibility.

Technorati tags:

Digg this article

Bookmark this article with del.icio.us

Previously: 8 Random Things

Next: Wanted: Podcast recommendations


Comments

Olly
2372 days ago

Nice work Mr P.

The only issue I’ve found is when I scale text up in IE6, it doesn’t re-scale the input to match, leading to an ugly overflow. I’m not sure if that’s a limitation of IE, but it’s something to be aware of.

#1
Nick
2365 days ago

Here’s something very similar using jquery if anyones interested. You’ll have to view source as i can’t be arsed with creating a standalone demo.
http://homepage.mac.com/nickaliwell/etribes/

#2
Scott Lenger
2364 days ago

I 100% agree with using label text vs. input attribute text (per your comment on 456) but I try to avoid z-index’ing as much as possible as they lend themselves to potential issues with the IE family of browsers.

#3
Jack Gordon
2357 days ago

The problem with this is what if the user has javascript turned off? I would probably set the positioning of the labels using js and leave the labels as they are for those without js.

#4