Using the HTML5 placeholder attribute with jQuery

Recently, I received my copy of the first title in the A Book Apart series: HTML5 for Web Designers by Jeremy Keith. I took particular interest in the Web Forms 2.0 section, and something which struck me as being very useful was the placeholder attribute, for use on text fields to give the user a pointer about of what sort of thing they should enter. Here's a good example:

<input type="email" name="email" placeholder="you@yours.com" />

Currently, Safari and Chrome make use of the attribute if you include it. If the field is empty and isn't in focus, they will show the placeholder text in a lighter colour. It's a pattern you're probably familiar with from all over the web, but implemented with JavaScript instead.

Unfortunately, at time of writing, only Safari and Chrome are implementing this behaviour. All other major browsers ignore the placeholder attribute. However, we can use the attribute itself to help us with a JavaScript fallback for browsers that aren't there yet. Here's what I've come up with for jQuery:

$(document).ready(function() {
    if (!elementSupportsAttribute("input", "placeholder")) {
        doPlaceholders();
    }
});

function elementSupportsAttribute(e, a) {
    return a in document.createElement(e);
}

function doPlaceholders() {
    $("input[placeholder], textarea[placeholder]").each(function() {
        $(this).focusin(function() {
            if ($(this).val() == $(this).attr("placeholder")) {
                $(this).attr("value", "").removeClass("placeheld");
            }
        }).focusout(function() {
            if ($(this).val() == "") {
                $(this).attr("value", $(this).attr("placeholder")).addClass("placeheld");
            }
        }).focusin().focusout();
    });
    $("input[type=submit], button[type=submit]").click(function() {
        $("input.placeheld").attr("value", "");
    });
}

To sum up what this script does:

  1. Once the page loads (via jQuery's $(document).ready method), the elementsupportsAttribute function (from Jeremy's book) is used to check whether the placeholder attribute is supported by the browser. If it is, no action is taken. If not, the doPlaceholders function is called.
  2. Each input with a placeholder attribute is assigned focusin and focusout functions which emulate the Safari/Chrome behaviour by inserting or removing the value from the placeholder attribute into the field where appropriate and indicating which state the field is in by the presence or absence of a placeheld class.
  3. The focusin and focusout functions are run once on each field so that any empty ones get their placeholder value automatically once the page has loaded.
  4. Each submit button is assigned a click function which will clear any fields with the placeheld class before the form is submitted, so that if a user has omitted a field, a blank value is sent to the server rather than the placeholder value (which could easily be a valid value and therefore may not produce an error message). Despite this, you should watch out for the placeholder being submitted in your server-side validation.

When included along with the jQuery library, the script will automatically work on any input element with a placeholder attribute on the page, and will not interfere with any native browser implementations. The code is totally portable so you won't need to touch it, but you probably will want to add a rule to your stylesheet so the fields in their "placeheld" state will have a lighter text colour:

input.placeheld {color: #888}

Use with caution

As well as this practical tool to implement the placeholder, it's worth taking time to consider its correct purpose. You shouldn't, for example, use it to label a field. label performs an important accessibility job and shouldn't be neglected, and besides, the placeholder disappears when you focus and stays gone if you fill the field, so it doesn't actually function well as a label. Also, the placeholder is supposed to act as a hint as to what sort of thing the user should input. Ideally, it should be obvious that it's a hint rather than a genuine value, so a user won't mistake it for being filled and valid. If you want to provide a default value, pre-fill the actual field with it.

Update 30 April 2011: Added support for <textarea>s.