Placeholder polyfill for IE < 10

|   Feb 19, 2015

Placeholders for old IE

The placeholder attribute is a great way to provide some hint text to help users as they’re filling out your form, or as a complete replacement for traditional headers/labels that describe each field in a form. But, since it’s not supported in Internet Explorer 9, you can’t use placeholders without a polyfill, otherwise those old IE users won’t know what each field is. In this article, I’ll describe how you can create a placeholder polyfill which will provide the exact same experience that you’d get with the placeholder attribute in modern browsers. This polyfill will work on <input> or <textarea> elements, but I’m just going to focus on <input> elements in this this article.

How it works

A <label> element is placed directly on top of the <input> element via absolute positioning, which appears to behave just like the native placeholder feature of modern browsers. The <label> is given a cursor: text style, so it behaves just like a text field when you hover over it with your mouse. The <label> must also use a for attribute to reference the <input> by its ID, so when the user clicks on the field to enter some text, they are actually clicking on the <label>, which immediately puts focus in the text field.

For modern browsers, the <label> is simply hidden via CSS, and the placeholder text is generated from the placeholder attribute on the <input> element.

Required markup:

<div class="placeholder_wrapper">
  <input type="text" placeholder="Enter your name" id="my_input" />
  <label class="placeholder" for="my_input">Enter your name</label>
</div>

One of the subtle effects that makes this feel just like a native placeholder is when the text gets lighter when the <input> field gains focus. This is achieved by using the :focus pseudo-class on the <input> and the + adjacent sibling selector to target the <label> to apply a different font color. And in order to keep this font color consistent across all browsers, the placeholder attribute can be targeted in modern browsers by using the vendor-specific pseudo-elements -webkit-input-placeholder, -moz-placeholder and -ms-input-placeholder.

Required CSS:

/* position the label directly on top of the input */
.placeholder_wrapper {
  position: relative;
}
label.placeholder {
  position: absolute;
  top: 0;
  left: 0;
  cursor: text;
}
 
/* hide the label in modern browsers or when text has been entered */
.inputplaceholder label.placeholder, input[placeholder].placeholder-state-hidden + label.placeholder {
  display: none;
}
 
/* input text color */
input[placeholder] {color: #404040;}
 
/* normal placeholder text color, slightly lighter than input text color */
input[placeholder]::-webkit-input-placeholder {color: #878787;}
input[placeholder]:-moz-placeholder {color: #878787;}
input[placeholder]:-ms-input-placeholder {color: #878787;}
input[placeholder] + label.placeholder {color: #878787;}
 
/* focused placeholder text color, even lighter than normal placeholder text color */
input[placeholder]:focus::-webkit-input-placeholder {color: #AEAEAE;}
input[placeholder]:focus:-moz-placeholder {color: #AEAEAE;}
input[placeholder]:focus:-ms-input-placeholder {color: #AEAEAE;}
input[placeholder]:focus + label.placeholder {color: #AEAEAE;}

Important: The font size, font family, font weight, line height and padding of the <label> must line up exactly with the <input>, so the the <label> text is in the same spot where those characters would appear in the underlying <input>.

Hide placeholder when text is entered

We want to keep showing the <label> until some text has been entered into the <input>. So, we have to hide the <label> when the field contains at least one character, and show the <label> when the text is cleared out. Text is most commonly added or removed by receiving input from the keyboard, so we have to listen to the keydown event. Since the keydown event fires before any new text gets inserted into the field, we have to check its value after a short delay (via setTimeout). We cannot use keyup for this because there would be too much of a noticeable delay when hiding and showing the placeholder text, depending on how long the user held each key down. Also note that the value can change when text is cut or pasted via the context menu, so we have to listen for cut or paste events as well.

To actually hide or show the <label>, we can just add/remove a placeholder-state-hidden class on the field, which lets CSS do the job of hiding/showing:

// jQuery
$(document).on('keydown cut paste', 'input[placeholder]', function() {
  var field = this;
  var initialValue = field.value;
  setTimeout(function() {
    if (field.value !== initialValue) {
      $(field).toggleClass('placeholder-state-hidden', field.value.length > 0);
    }
  }, 0);
});

In order to also handle text being added by the native browser autocomplete suggestion list, you should also add an event-listener to respond to the propertychange event, and toggle the placeholder-state-hidden class accordingly. This event only fires in IE < 10, when the field does not have the autocomplete="off" attribute.

Placeholder feature detection

Rather than checking the User Agent for certain Internet Explorer versions, you should use feature detection to determine when to set up this polyfill. By adding a class to the <html> element, we’ll let CSS hide the <label> in modern browsers. If you’re already using Modernizr, you can easily set up a test to provide classes for you:

// Adds an "inputplaceholder" or "no-inputplaceholder" class to the <html> tag
Modernizr.addTest('inputplaceholder', function() {
  return Modernizr.input.placeholder;
});

Or you could do the check yourself:

if ('placeholder' in document.createElement('input')) {
  document.documentElement.className += ' inputplaceholder';
}
 

Demo

Finally, here’s what it looks like in-action. This is a video taken from IE 9 on Windows 7:

Placeholder in IE9

Code on Github

github.com/MoonScript/placeholder-polyfill

Leave a comment

Your email address will not be published. Required fields are marked *

Connect with Facebook

Sign up to receive email communications regarding events, webinars, and product news.

What is Socialcast?

Socialcast by VMware (NYSE: VMW) is a social network for business uniting people, information, and applications with its real-time enterprise activity stream engine. Behind the firewall or in the cloud, Socialcast enables instant collaboration in a secure environment. Socialcast is headquartered in San Francisco, California. www.socialcast.com