HTML5 placeholder and an alternative approach – introducing Robert’s playground

Looking at HTML5 and the placeholder functionality, it’s there to offer a hint to the user before they have started filling out something. But what if that’s not the best way?

In the placeholder section in the HTML5 specification it says:

User agents should present this hint to the user, after having stripped line breaks from it, when the element’s value is the empty string and the control is not focused (e.g. by displaying it inside a blank unfocused control).

Very clear and concise, and every web browser seem to have implemented in the same fashion. All good and well, right? Well, in my current project the UX Designer said she didn’t want that behavior, but rather the native way iOS handles it. My initial reaction was:

No, you’re wrong, of course. That’s not in the specification and not how web browsers implemented it.

However, after that I decided to take a more humble approach, to look at the iOS implementation, evaluate it and see which one was best. The very slight distinction between iOS and the HTML5 way is that iOS keeps the hint/placeholder text when the element gains focus and removes when you have actually started entering something.

And honestly, I must say that that is quite a nice way to do it. When you have set focus to the field, you might have forgotten what the hint said, but if it’s still there it makes thing a bit easier.

Introducing my playground and an alternative placeholder approach

I’ve created a new section of my web site, Robert Nyman’s playground. It’s like Tommy Lee’s Tommyland, but not the same. I wish. Or not. Well, maybe… Anyway… It’s where I will code things together to play around and show demos. As opposed to my HTML5 or CSS3 sections that are more tested and lists web browser support etc, the things in the playground might or might not work for you – if they don’t, and you know why, please let me know.

All the code is also available on GitHub in the robnymanplayground project, where you can look at it, fork it or experiment in any way.

In the playground, I have created the Alternative placeholder behavior where you can test this behavior and see if you prefer it. It works in all the latest versions of Firefox, Google Chrome, Safari, Opera and Internet Explorer, but should work in older versions as well. What it does is:

  • Offer placeholder behavior the way it is in iOS.
  • Clear the form fields from default placeholder text if nothing was entered.
  • Supports the behavior for password fields as well, switching between text and password field display.

The code looks like this:

HTML

<form action="index.html" novalidate>
    <input type="text" name="first-name" placeholder="Enter first name">
    <input type="text" name="last-name" placeholder="Enter last name">
    <input type="tel"  name="phone-no" placeholder="What is your phone no?">
    <input type="email" name="email-address" placeholder="Enter your e-mail address">
    <input type="text" name="user-pwd" data-type="password" placeholder="Choose a password">
    <input type="text" name="user-pwd-repeat" data-type="password" placeholder="Repeat password">

    <input type="submit" value="Send to myself">
</form>

JavaScript

var dataPlaceholders = document.querySelectorAll("input[placeholder]"),
    l = dataPlaceholders.length,
    
    // Set caret at the beginning of the input
    setCaret = function (evt) {
        if (this.value === this.getAttribute("data-placeholder")) {
            this.setSelectionRange(0, 0);
            evt.preventDefault();
            evt.stopPropagation();
            return false;
        }
    },
    
    // Clear placeholder value at user input
    clearPlaceholder = function (evt) {
        if (!(evt.shiftKey && evt.keyCode === 16) && evt.keyCode !== 9) {
            if (this.value === this.getAttribute("data-placeholder")) {
                this.value = "";
                this.className = "active";
                if (this.getAttribute("data-type") === "password") {
                    this.type = "password";
                }
            }
        } 
    },

    restorePlaceHolder = function () {
        if (this.value.length === 0) {
            this.value = this.getAttribute("data-placeholder");
            setCaret.apply(this, arguments);
            this.className = "";
            if (this.type === "password") {
                this.type = "text";
            }
        }
    },

    clearPlaceholderAtSubmit = function (evt) {
        for (var i=0, placeholder; i<l; i++) {
            placeholder = dataPlaceholders[i];
            if (placeholder.value === placeholder.getAttribute("data-placeholder")) {
                placeholder.value = "";
            }
        }
    };

    for (var i=0, placeholder, placeholderVal; i<l; i++) {
        placeholder = dataPlaceholders[i];
        if (placeholder.value.length === 0) {
        placeholderVal = placeholder.getAttribute("placeholder");
        placeholder.setAttribute("data-placeholder", placeholderVal);
        placeholder.value = placeholderVal;
        placeholder.removeAttribute("placeholder");
        if (placeholder.type === "password") {
            placeholder.type = "text";
        }
    }
    else {
        placeholder.className = "active";
    }
    
    // Apply events for placeholder handling         
    placeholder.addEventListener("focus", setCaret, false);
    placeholder.addEventListener("drop", setCaret, false);
    placeholder.addEventListener("click", setCaret, false);
    placeholder.addEventListener("keydown", clearPlaceholder, false);
    placeholder.addEventListener("keyup", restorePlaceHolder, false);
    placeholder.addEventListener("blur", restorePlaceHolder, false);
    
    // Clear all default placeholder values from the form at submit
    placeholder.form.addEventListener("submit", clearPlaceholderAtSubmit, false);

Call for a change?

What do you think? Do you prefer the iOS approach with a longer lingering of the hint text? Should we submit this as a change to HTML5 and current implementations in web browsers?

62 Comments

  • Note that OS X Lion will also have iOS-like placeholder behavior (not just in Safari, but OS-wide, that is).

  • That’s an interesting solution.

    I’ve been using placeholder for a while now. And in most projects I’ve had to revert to using JS before launch because of inconsistencies between browsers, and inability to properly style the placeholder text before focus.

    I also have a recent project where, for a moderate form (30+ fields) the labels have been designed as placeholders (much like your demo).
    When you focus the field the “label” disappears and you actually have no idea what you should type in anymore.

    Will give this a try, thanks.

  • Yoav Weiss says:

    Current HTML5’s placeholder behavior (i.e. placeholder disappears when input box is focused) renders the placeholder irrelevant since it is not there when the user actually needs it. The iOS way makes more sense. Behavior should have been controlled by an attribute…

  • Interesting, though the email and tel types act up a bit weird in Opera (the cursor sticks wherever I click in the text, while the other inputs have the cursor at the front).

    With regard to passwords, this is a good read, though I’ve yet to find anyone applying it on the web: http://www.useit.com/alertbox/passwords.html

  • Balázs says:

    I have actually found myself tabbing to another input & back to see the placeholder again, so I also like this implementation.

    From markup & js perspective I do like to start off with html that only needs a little js love to improve. What I mean by that is using existing attributes and setting types as expected, than doing js magic on it to change default behaviour. So in this case the password input, I believe, should start by being type=”password” and all inputs should have the placeholder attribute and only do the modifications when initing the script.

    I quickly did the changes myself: http://jsfiddle.net/bfjST/1/

    But otherwise I totally like it 🙂

  • stryju says:

    few things:

    1. when You focus the field that’s been filled with “placeholder” value, it jumps to the position 0 of string – even when You select some part of it
    2. “placeholder” is selectable, when focusing field

  • This is exactly the right behaviour, Rob. How to implement it in script has always been a difficulty in my mind — handling caret positioning and re-positioning in particular, and when exactly to trigger which events — but this looks really good. Will have to try and break it 😉

    @Jordi
    The notion of giving visual feedback for the textual input in password fields is extremely controversial. After Jakob published this, a number of front-end-focussed sites (ie by front-end geeks for front-end geeks) implemented it — some without notifying the user up front that their password would be written in the clear. The important thing to remember is that this is not merely a matter of convenience — any metrics dictating that it does actually make the login experience faster and more convenient do not account for the user’s security or sense thereof, which are harder to measure.

  • @Barney: Agreed about the passwords, it should definitely be opt-in like it is on Android phones (and perhaps others), you have box you can check to see your password. Check it if you feel confident nobody’s looking.

    But it just struck me that in this case, if you’re gonna rely on javascript to “secure” your password field, you might as well go the full length and try something new.

    Anyway good to know, I wasn’t aware of the history accompanying Nielsen’s post.

  • Ege Özcan says:

    The only problem I see is that it fails when text is dropped by mouse onto the field. Other than this small annoyance, it works perfectly…

  • While I really like the general behavior here, I think it’s a bit visually disconcerting that the placeholder disappears as soon as you press shift in one of the text fields. Personally, I’d prefer it if the placeholder remained until a specific character was typed. That being said, your current version is already a major improvement over the “official” HTML5 behavior.

  • I know this isn’t the most recent browser, but using FF 3.6, all the fields work except the password ones. When I type in a letter, it disappears and reverts back to the placeholder. If I quickly type in 2 letters, the first one disappears and the second one stays in the box. Not sure why it does this, but thought I would offer up the problem in case anyone wants to take a look for a solution.

  • Christian says:

    Quirky! I do like it. You should try it on Firefox (v 3.6.16 & 3.6.17). I get some strange results with the password field.

    I agree with @Jordi Boggiano, unmask the password.

  • Aaron Wagner says:

    I can’t SHIFT+TAB to change focus to the previous input unless I hold down SHIFT and press TAB twice. Otherwise, I like it.

  • Robert Nyman says:

    Thanks for the comments, everyone!

    Mathias,

    Interesting, I didn’t know that! I still think this would benefit all users, no matter the operating system, though.

    Andrei,

    Please do and let me know what you think.

    Yoav,

    Glad you agree!

    Jordi,

    Yes, Opera behavior seems a bit shaky – I’m guessing it’s because of experimental implementation of new HTML5 form fields.

    Like pointed out by Barney, I think it’s important to consider the cons of that approach too, and the possible risks with a JavaScript approach like this. For now, I’m not going to change it.

    Balázs,

    I agree, and I’ve now changed the code to utilize native placeholder attributes and then override them if JavaScript is enabled.

    stryju,

    1. That’s the general behavior of placeholders, that it should just start at the beginning. However…
    2. I’m not gonna cover text selection now, but yes, it would be preferred to block that for the placeholder text.

    Barney,

    Thanks! Glad you like it, and thanks for the input on password fields.

    Ege,

    Thanks! Yes, and that implementation is broken in various web browsers. For instance, in Google Chrome it triggers the focus event, not the drop event, but still places the dropped text in the field… For now, I’m not gonna tweak that further, but feel free to fork the project on GitHub and play around with it.

    Jonathan,

    I agree, and I have fixed the behavior when the Shift key is pressed.

    Molly, Christian,

    Hmm. I couldn’t reproduce that behavior on Firefox 3.6.16 on Mac at least. Which platform are you on?

    Aaron,

    Yes, that was an annoyance, and I have fixed that now.

  • NICCAI says:

    +1 for me. The other issue I have grappled with is when using placeholder in lieu of a label during edit. Example would be when a home and mobile phone are filled. The user can’t discern (without familiarity) which number is which. I think I might use :before/after to deal with this. Not the most accessible solution, but…

  • Robert Nyman says:

    NICCAI,

    You’re right, and I’ve updated the demo to have labels as well, just to make things more clear that placeholders and levels aren’t the same.

  • Ionut Staicu says:

    I also made a jQuery implementation of placeholder for older browser. Is in romanian, but the code is universal, right? 😛

  • […] the background as to why I’m writing what you’re about to read, please read this blog post. For those who don’t want to read it, the short version is that the current implementations […]

  • Robert Nyman says:

    Ionut,

    Code is definitely universal. 🙂 Thanks for the tip!

  • Rob, RE: weird password field behavior –

    I’m also getting a strange jump when trying to type in the two password fields. If I type slowly: “p…a….s…s…” the field goes blank for each letter, then a quick visual of a password field with lots of “*”s “onKeyUp”, then the placeholder text reappears and my typed letter seems to be gone. If I type quickly, or if I hold down a key, it seems my keypress is faster than the action of the javascript and I can start typing normally (as long as I don’t delete all of the characters that I type, then it’s back to square one.)

    I’m running Firefox 3.6.17 on Ubuntu 10.10.

  • Robert Nyman says:

    Jen,

    Thanks for the great description! Off the top of my head I’m not sure how to address that behavior, and also, not sure if I’ll put more time into doing that right now.

    However, if you (or anyone else) have a good suggestion how to do that, please let me know!

  • Joel Meador says:

    On your demo page, the labels don’t have for targets / don’t wrap the inputs. If you care about that for the demo page. 🙂

  • Robert Nyman says:

    Joel,

    Thanks! That’s what I get for doing something too quick… 🙂 I’ve added for attributes to the id fields – when it comes to label wrapping, though, I’m not really a fan of it.

  • Daniel Maier says:

    It totally froze and my iPhone 4. In fact the entire browsing experience on this website is super slow. I don’t know if it is my phone or something here. Running FW 4.3.2

  • Kurt Milam says:

    What do I think? I think the iOS placeholder behavior is useful, but also I think that this particular implementation of it is broken, from the ground, up – I honestly don’t think it’s worth forking and trying to fix.

    I think that putting the text into the actual inputs is the wrong way to go about it, and I also think that publicizing half-tested code that’s nowhere near working is lazy and not particularly helpful. The problem with publicizing this kind of code is that you may have solved 50% of the problem, but the other 50% may be unsolvable using your base – in other words, a complete rewrite may be required, rendering the original code useless and wasting a lot of people’s time.

    Sorry to be blunt, but you did ask what your readers thought.

    Two alternate and, in my opinion, much cleaner implementations of this functionality – that are tested, work in most modern browsers and don’t have any of the problems associated with putting the placeholder text inside the actual inputs – can be found here: http://attardi.org/labels/ . Attardi uses the anchor’s title attribute, but his code can be easily modified to use the placeholder attribute, instead.

  • Robert Nyman says:

    Daniel,

    Did the demo page freeze for you? I can imagine that it has to do with the text handling and setting the caret.

    My web site is not slow for me on an iPhone 3G, but the comment form here might be – there’s something in tracking key inputs that make it sluggish.

    Kurt,

    Good to hear that you like the iOS implementation.
    And I respectfully disagree about your assessments about the demo, for a number of reasons:

    – It showed a lot of people how it could work on the web, directly in web browsers. Given the attention it has gotten, I’d argue that is quite helpful.

    – Using labels and positioning them has its accessibility problems, and it also becomes a problem with focusing elements and hooking into typing accordingly. Hence putting the text into the input fields works, especially since it’s cleared ad submit if it haven’t changed.

    – Since it works in major web browsers I’d say it’s pretty far from “nowhere near working”. Caveats are password fields and drag and drop of text. The former could pose a issue in an older version of Firefox, but don’t use it for that then/in that version; the latter is probably a small use case that can be fixed if anyone wants to put the effort into it.

    And interesting about about Attardi’s code. The problem with that, though, is that labels and placeholders are confused with each other: they aren’t the same thing.

  • […] See the article here: HTML5 Blog on: Jan Tißler: HTML5 placeholder and an alternative approach – introducing Robe… […]

  • Dan Denney says:

    First off, thank you for putting this experiment together. The functionality is exactly what we want on our project and we’re rolling it out.

    Has anyone else run into trouble with IE8? I see no mentions of issues from anyone, but I can’t seem to get it to function. I get the fun “object doesn’t support this property or method”, which we narrowed down to IE8 not supporting addEventListener.

    So, I tried this format instead:

    if (!placeholder.addEventListener) {
    placeholder.attachEvent(“focus”, setCaret);
    }

    else {
    placeholder.addEventListener(“focus”, setCaret, false);
    }

    The good news is that the js error goes away, the bad news is that the functionality goes away. The placeholder text is there, but it’s treated like regular text. (I’m guessing because IE8 is attaching the event to the window, not the element.)

    Anyhow, I’d love to know if anyone has run into this and/or solved it. I tried a lot of things and did a good deal of searching to try and figure it out, but it’s a bit over my head.

  • Robert Nyman says:

    Dan,

    Thanks!
    For IE8, it might be good to look at the options at Microjs or if you already use an existing JavaScript library your page, to utilize that for it.

    You could also potentially run into problems with TextRange handling in older versions in IE, so look into the options there as well.

  • I want to confirm that on Samsung Galaxy Tab model GT-P1000 Your code working well. The browser used by me was Miren Browser.

  • Robert Nyman says:

    Cezary,

    Great, thanks for letting me know!

  • I have little suggestion: could you add a link in footer named “back to top”? When the content is read to the bottom of page the fastest way to back on the top of page is click on the link as I described. Using only fingers is much slower.

  • Robert Nyman says:

    Cezary,

    On this page? Can’t you just tap the title bar like in iOS to scroll to the top?

  • Masataka Yakura says:

    FYI there was a WebKit bug titled “Allow platforms to specify if the placeholder should be visible when text controls are focused” opened and fixed by an Apple engineer in February. So I guess WebKit will keep placeholder text rendered on focus in Lion (and possibly in iOS5?)

    https://bugs.webkit.org/show_bug.cgi?id=53740

  • Robert Nyman says:

    Masataka,

    Interesting – thanks for letting me know!

  • […] attributet syns som text i formulär fältet för att ge en hint om vad man ska skriva in. Robert Nyman har skrivit här, om hur man via javascript kan se till att texten inte försvinner förrän användaren verkligen börjar att skriva i fältet. Alltså istället för att användaren […]

  • Remy Sharp says:

    A little late to the party but wanted to add some feedback: first up, good stuff, however on the iPad (and I’m testing the ipad2 to let’s remember that it’s faster than the ipad1) the form field feels sluggish to respond.

    I’d recommend caching the placeholder somewhere in the lib to get out of constantly hitting the DOM – not that I’m entirely sure that’s the root cause of the sluggishness. It’s not huge, but it’s enough to notice something feels off.

  • Robert Nyman says:

    Remy,

    Thanks!
    We’ve been using this on iPad 1 at work and it has been working decently. However, I do agree in general that detecting key inputs in the normal fashion and making actions depending on that is generally not that nice on iOS.

    It seems to be mostly about key input detection, and I hope there are other alternatives to making it smoother.

  • Aldrik says:

    Hi Robert,

    For all modern browsers this can be achieved using CSS alone.

    This implementation currently breaks pasting the X/X11 selection clipboard. In Firefox it fails to input anything and in WebKit it appends the placehoder text.

  • Robert Nyman says:

    Aldrik,

    While CSS with overlaying elements could be an approach, it’s not really the same as this. Besides, some of the CSS pseudo-classes needed haven’t been available that long in some web browsers.

    Sorry about X11, my testing has worked on Mac and PC.

    Most of all, though, it’s more of a demo to indicate how it could behave (when it works, that is :-P).

  • harith says:

    Here is a slightly different approach to exhibit the same behaviour. Instead of placing text in the input box, I put the placeholder text in a span and position it exactly behind the input. Since the text is not in input box, it does not intrude with validation.

    A little additional css allows you to dim the placeholder when the input box is in focus. Feels good.

    The implementation is not robust and did not undergo extensive testing. But, the code is on github.

  • Robert Nyman says:

    harith,

    Nice, thanks for the tip!

  • […] Meant to be able to display a hint to the end user what to input. (Side note: I wrote a blog post discussing the desired behavior of the placeholder attribute) […]

  • Brenden says:

    This is definitely how it should work.

    I’m on a project now that I want to do just this. Give a field focus with the placeholder visible until the user begins typing.

    What can we do to get this into the HTML5 standard?

  • Robert Nyman says:

    Brenden,

    Glad you think so!
    I guess talking to the WHATWG’s mailing list could help with that.

  • Henrik N says:

    Thanks! Adapted it for jQuery and CoffeeScript here: https://gist.github.com/1245969

  • Robert Nyman says:

    Henrik,

    Great, thanks for sharing!

  • […] Meant to be able to display a hint to the end user what to input. (Side note: I wrote a blog post discussing the desired behavior of the placeholder attribute) […]

  • […] Probably not a lot of use, but here's an alternative approach of doing the same thing… robertnyman.com/2011/05/02/html5-placeholder-and-an-alternative-approach-introducing-roberts-playgro… As you can see from the demo, the placeholder text remains visible until the user actually starts […]

  • josh says:

    This doesn’t work in IE7 or IE8?

  • Robert Nyman says:

    Nataniel,

    Cool, thanks for letting me know!

    josh,

    No, it only works for web browsers that support the placeholder attribute.

  • Morris says:

    Another implementation is to change the input background to transparent, and show the place-holder text in an element behind the input.

    That avoids a variety of odd bugs that can occur using the technique of modifying the value field (e.g. cut and paste, mouse selection, uncommon browser issues, fitting in with existing code that expects value to be the actual value, etc etc).

  • Robert Nyman says:

    Morris,

    It is. This was mainly to show the desired behavior, which has now been implemented in Google Chrome and will, to my knowledge, be in Firefox too.

  • Dilip says:

    The above alternatives doesnt work for Samsung galaxy tab

    if i am typing 201 and programatically insert ‘-‘ symbol the cursor position stays after 1 but not after ‘-‘ symbol

    setcaretpos and initkeyevent doesnt work – any other ways to make this work ?

  • Robert Nyman says:

    Dilip,

    I’m sorry, but I have no idea why it doesn’t work there.

  • Jordan says:

    Great solution !!! Thank you for that !
    …and hey, can I use that in my website Robert?

  • Robert Nyman says:

    Jordan,

    Absolutely!

  • Danny says:

    I have just done a native html5 placeholder… and it acts the way you describe if it were on iOS.

  • Hi Robert,

    its been a long time since your post, but recently I got a task to correct placeholder behavior for ie10, so I attempted to create jQuery plugin that features your ideas. I also added workaround for the browsers that can’t change type of password input.

  • Robert Nyman says:

    Andrey,

    Nice, thanks for sharing!

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.