Adding HTML5 placeholder attribute support through progressive enhancement

I continually talk about HTML5 and how progressive enhancement is a simple approach to make any new behavior possible in web browsers that haven’t implemented it yet. I thought I’d show you a simple example how to do this with the new placeholder attribute for input elements.

Introducing the placeholder attribute

The placeholder attribute is there to show the user a text, a hint of sorts, but as soon as the text field gets focus, you want that value to be cleared. All the HTML5 code it takes is:

	<input type="text" id="search-text" placeholder="Enter terms here">

However, the status of implementation right now is that only WebKit-based web browsers (Google Chrome and Safari) support this. So, what do we do for older web browsers?

For web browsers not supporting the placeholder attribute

There are two things we need to add to get this in web browsers not supporting it:

  • A certain class to display our created placeholder in a semi-disabled fashion
  • A JavaScript snippet to simulate the placeholder attribute behavior

CSS

	<style>
		.placeholder {
			color: #aaa;
		}
	</style>

JavaScript

This JavaScript is based on using jQuery for class adding/removing and event handling, but naturally you could use just about any JavaScript library or just write it yourself. Just keeping it short and simple here, ok? :-)

	<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
	<script>
		// To detect native support for the HTML5 placeholder attribute
		var fakeInput = document.createElement("input"),
			placeHolderSupport = ("placeholder" in fakeInput),
			clearValue = function () {
				if (searchField.val() === originalText) {
					searchField.val("");
				}
			};

		// Applies placeholder attribute behavior in web browsers that don't support it
		if (!placeHolderSupport && confirm("Yeah?")) {
			var searchField = $("#search-text"),
				originalText = searchField.attr("placeholder");

			searchField.val(originalText);
			searchField.addClass("placeholder");

			searchField.bind("focus", function () {
				searchField.removeClass("placeholder");
				clearValue();
			});

			searchField.bind("blur", function () {
				if (searchField.val().length === 0) {
					searchField.val(originalText);
					searchField.addClass("placeholder");
				}
			});

			// Empties the placeholder text at form submit if it hasn't changed
			searchField.parents("form").bind("submit", function () {
				clearValue();
			});

			// Clear at window reload to avoid it stored in autocomplete
			$(window).bind("unload", function () {
				clearValue();
			});
		}
	</script>

Progressive enhancement

This is an easy example of progressive enhancement: first check for native support, and if it’s not there, implement the same behavior through JavaScript (if JavaScript is available, of course).
Happy scripting!

42 Comments/Reactions

  • #1 Johan
    June 17th, 2010 at 16:42

    Nice! But i’d call it total enhancement since it’s enhancing the browsers not supporting the placeholder attribute to :P

  • #2 Mathias
    June 17th, 2010 at 16:47

    I spot a few possible optimizations…


    // To detect native support for the HTML5 placeholder attribute
    var fakeInput = document.createElement("input"),
    placeHolderSupport = ("placeholder" in fakeInput);

    Could be written as:


    // To detect native support for the HTML5 placeholder attribute
    var placeHolderSupport = ('placeholder' in document.createElement('input'));

    Better yet, don’t use the placeHolderSupport (should really be placeholderSupport btw) variable and just put the above code inside the if check.

    var searchField = $("#search-text"),
    originalText = $("#search-text").attr("placeholder");

    This queries the DOM twice looking for an element with the ID search-text. Please don’t even do that. Since you’re storing a reference to the jQuery object for that element anyway, why not reuse that?

    var searchField = $("#search-text"),
    originalText = searchField.attr("placeholder");

    The following looks a bit silly:

    if (searchField.val().length === 0) {}

    You can just use this instead:

    if (!searchField.val().length) {}

    Your code will not work for more than one element. It would probably be an even better example when written as a generic jQuery plugin.

    Of course, this is something that has already been done several times.

    Having said that, great article! Good to see you raising awareness for the HTML5 placeholder attribute.

  • #3 Robert Nyman - author
    June 17th, 2010 at 17:10

    Johan,

    Well, to me it’s progressive, but I can live with that name too. :-)

    Mathias,

    About support check and those variables, it could definitely be made shorter. Same goes for just one element as opposed to having a loop and find every element with a certain class.

    But, bear in mind that this is as much as teaching someone about it and making that line of thinking as clear as possible, and not just about offering a solution to include and be done.

    What I definitely do agree about, though, is the check for the placeholder attribute value when that element has already been found, and I’ve updated the code for that.

    And, good work putting together plugins for people. :-)

  • #4 alexander farkas
    June 17th, 2010 at 17:21

    You can also use jQuery’s support object to store informations about browser features:

    $.support.placeHolder instead of placeHolderSupport

  • #5 Andreas
    June 17th, 2010 at 17:22

    I think your example is a misuse of the placeholder attribute, cause it should give the user a hint how the input data should look like (see the spec). What you got here is a label. As you remove the value at focus the value will never be read by a screenreader so its not a real progressive enhancement. Btw. I’m not sure how screenreader will handle the placeholder.

  • #6 Robert Nyman - author
    June 17th, 2010 at 17:29

    alexander,

    Good point!

    Andreas,

    I agree, my example wasn’t all clear, and it should have been more hint-y. I think in regards to the placeholder attribute, the support isn’t really there yet in screen readers.

    But if I’m not mistaken, screen readers should at least be able to read the value of a text field before it actually gains focus, right? And maybe it’s something we can use WAI-ARIA Live for alerting them on the change at focus?

  • #7 sil
    June 17th, 2010 at 17:46

    It should probably check to see if the searchfield’s value attr was already set in the HTML, no? :)

  • #8 sil
    June 17th, 2010 at 17:48

    …and remove the placeholder text on form submit, thinking about it ;)

  • #9 Robert Nyman - author
    June 17th, 2010 at 17:55

    sil,

    Yes, and yes. :-)
    But for that, I refer to other people’s complete solutions for every scenario and not this code that is here for inspiring. :-)

  • #10 Joe Critchley
    June 17th, 2010 at 18:01

    Ha! You beat me to it with this article.

    May I suggest not interfering with the val attribute though, as that means it is submitted with the form. Perhaps text overlaid on the input would be better?

  • #11 sil
    June 17th, 2010 at 20:18

    Robert: what, like http://www.kryogenix.org/code/browser/labelify/ ? :) Although it uses label rather than placeholder because placeholder didn’t exist two years ago when I wrote it ;)

  • #12 Remy Sharp
    June 17th, 2010 at 23:24

    Oh Robert….there’s a nasty bug in the code :(

    I wrote a “hint” jQuery plugin a long while back, but also I’ve also ported this to support placeholder (as you’ve done too) via a gist.

    So what’s the really big bug? What happens if the form is submitted without the field being focused? … I know you’ll spot it ;-)

  • #13 alexander farkas
    June 18th, 2010 at 0:52

    i made a ready to use plugin out of it, including some improvements:
    http://gist.github.com/442875

  • #14 protofunc() » HTML5 placeholder Attribut und Zugänglichkeit
    June 18th, 2010 at 8:48

    [...] durch Robert´s Post/Script zu “Adding HTML5 placeholder attribute support through progressive enhancement” und vor allen Dingen einigen Kommentaren habe ich mein eigenes HTML5 Placeholder-Script [...]

  • #15 Robert Nyman - author
    June 18th, 2010 at 14:57

    Joe, Remy,

    I understand the problem, and I have added code that clears the mimicked placeholder text before submit, if it hasn’t changed.

    sil,

    Absolutely, it’s pretty much the same thing. :-)

    Remy,

    Thanks for the suggestions!

    alexander,

    Great, thanks!

  • #16 Kenneth Sundqvist
    June 29th, 2010 at 9:42

    I’d like to remind you to always set a background along with any color you set on form elements, and vice versa.

    I’m a user of dark desktop themes and form elements use that dark style, so I regularly end up with dark text on dark backgrounds, having to use Firebug and userstyles to rectify these problems. A serious usability issue.

    So set both color and background, or leave it to its default.

  • #17 Robert Nyman - author
    June 29th, 2010 at 12:25

    Kenneth,

    Good input!

  • #18 c69
    July 15th, 2010 at 11:33

    Quite an elegant solution )

  • #19 Emil Stenstörm
    September 1st, 2010 at 17:36

    I looked at jQuery plugins for placeholder the other day, and there’s one thing that many of them, and your code is missing. How do you handle password inputs? The placeholder should show the text for password fields, but your code shows them as stars. Since the type attribute can’t be changed on password fields, you need to construct a separate field and replace the password one.

    Tricky, and annoying.

  • #20 Robert Nyman - author
    September 1st, 2010 at 20:41

    c69,

    Thanks!

    Emil,

    Good point! Either that replacement approach is one way to go, or perhaps using an absolutely positioned label element or so. Neither solution is a nice one, though.

Write a comment

Twitter reactions

Share your thoughts:

HTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> . If you want to display code examples, please remember to write &lt; for < and &gt; for >.

Comment preview