How to make the input placeholder more user friendly

I’ve always loved placeholder text for input fields. Not too long ago the only way to achieve this would be to create a special javascript function that enabled the desired functionality, but now it magically comes pre-built into HTML5. Incase you’re wondering, placeholder text is the text within an input field that disappears once you click on it. It’s often used in place of a label.

How is it not user friendly? tl;dr – Take me to the tutorial already

Placeholder text can be very helpful and can save a lot of page space while also being aesthetically pleasing. With this great feature, however, comes a problem: If the placeholder text is being used in place of a label, it can become very confusing when you focus on the field and the ‘label’ disappears.

It’s important for users to know:

  • What field they are currently on
  • What field they have filled in

Typical input placeholder problem

Figure 1 - Standard input placeholder problem
Which input field am I on?

Based on the image above, it’s impossible to tell what the first/focused field is. It is relatively simple to deduce it’s either a ‘username‘ or ‘email‘ field. The only way to find out which field you’re on would be to remove all the text in the field and blur (lose focus). I have personally been caught by this dozens and dozens of times and I find it very annoying.

One method that websites, such as Twitter, have been adopting is to have the placeholder text fade out slightly on focus, but only disappear once the user inputs some text. This is arguably the way that the HTML5 placeholder should work by default.

An improved version

Figure 2 - The Twitter input placeholder

  1. Normal Placeholder text
  2. Placeholder text fades out slightly on focus
  3. The input field is unknown once text has been added
  4. The title attribute is used to add information

The method that the Twitter login system uses is a big step up from the problem in fig.1, however the same problem still exists once the user has added text.

The title attribute has been used here so a user can see the placeholder text by hovering over the input field which is a great addition. Unfortunately in general, I still don’t feel this is as very user friendly as it could be.

The solution

I would like all of the bonuses of both the placeholder method and the standard label method. I’ve decided there is one basic way to achieve this: Have either the label of the input field or an appropriate icon appear to the right of the field after the field has received focus.

So that’s it, in this tutorial I’m going to show you how you can make a form with placeholder text that is semantic, user-friendly and degrades gracefully for legacy browsers.

The HTML

The following HTML is normal <form> markup. It’s what we do with the CSS that really matters.

<form id="login">
    <ul>
        <li>
            <input id="email" name="email" placeholder="Your Email" title="Your Email" type="email" required />
            <label for="email">Your Email</label>
        </li>
        <li>
            <input id="password" name="password" placeholder="Your Password" title="Your Password" type="password" required />
            <label for="password">Your Password</label>
        </li>
        <li>
            <input id="submit" name="submit" type="submit" value="Login">
        </li>
    </ul>
</form>

The CSS

#login{font-size: 12px; margin: 0 auto; width: 700px;}
#login li{float: left; list-style: none; margin-left: 30px; position: relative;}
#login li:first-child{margin-left: 0;}

label{line-height: 40px; position: absolute; right: 120px; top: 0; bottom: 0;
    -moz-transition: 0.3s right ease;
    -ms-transition: 0.3s right ease;
    -o-transition: 0.3s right ease;
    -webkit-transition: 0.3s right ease;
    transition: 0.3s right ease;
 	z-index: 0}

input{color: transparent; font-size: 12px; height: 35px; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px;
    -moz-transition: 0.3s all ease;
    -ms-transition: 0.3s all ease;
    -o-transition: 0.3s all ease;
    -webkit-transition: 0.3s all ease;
    transition: 0.3s all ease;}

input[type="email"], input[type="password"]{border: 1px solid #ccc; height: 35px; padding: 0 10px; width: 240px; position: relative; 
	-moz-box-shadow: inset 0 0 10px rgba(0,0,0,.06);
	-webkit-box-shadow: inset 0 0 10px rgba(0,0,0,.06);
	box-shadow: inset 0 0 10px rgba(0,0,0,.06);
	z-index: 2;}

input[type="email"]{color: rgba(47,130,194,.8);}
input[type="password"]{color: rgba(237,28,112,.8);}

/* Placeholder */
input[type="email"]:-moz-placeholder{color: rgba(47,130,194,.6);}
input[type="email"]:-ms-input-placeholder{color: rgba(47,130,194,.6);}
input[type="email"]::-webkit-input-placeholder{color: rgba(47,130,194,.6);}

input[type="password"]:-moz-placeholder{color: rgba(237,28,112,.6);}
input[type="password"]:-ms-input-placeholder{color: rgba(237,28,112,.6);}
input[type="password"]::-webkit-input-placeholder{color: rgba(237,28,112,.6);}

/* Label */
input[type="email"] + label{color: rgb(47,130,194);}
input[type="password"] + label{color: rgb(237,28,112);}

input:focus + label{right: 10px;}

input[type="email"]:focus, input[type="password"]:focus{background-color: rgba(255,255,255,.8);}

/* Submit */
input[type="submit"]{
	background-color: #333;
	background: -moz-linear-gradient(bottom, #333, #444);
	background: -ms-linear-gradient(bottom, #333, #444);
	background: -o-linear-gradient(bottom, #333, #444);
	background: -webkit-linear-gradient(bottom, #333, #444);
	background: linear-gradient(bottom, #333, #444);
	border: 1px solid #222; color: #fff; cursor: pointer; height: 35px; width: 110px;
}

input[type="submit"]:hover{color: #ff6937;text-shadow: 0 0 1px rgba(255,255,255,.2);}

The CSS mostly consists of general styling, I’d say the most important two lines are:

input:focus + label{right: 10px;}
input[type="email"]:focus, input[type="password"]:focus{background-color: rgba(255,255,255,.8);}

So the label is absolutely placed behind the input field. On focus the label moves to the right while the input’s background fades to a lower opacity. This gives the illusion of the label sliding right while fading in.

That’s pretty much all there is to it. I think it’s a neat little trick.

Let’s give IE a bit of love

As always, IE spoils the party, but as always Modernizr is here to save the day. We can get the form to act almost identically (sans animations) on IE8 and functionally on IE 6 and 7. Firstly, make sure you’ve given either the <html> or the <body> tag IE specific styles. For example:

<!doctype html>
<!--[if lt IE 7 ]> <html class="no-js ie6 ie" lang="en"> <![endif]-->
<!--[if IE 7 ]>    <html class="no-js ie7 ie" lang="en"> <![endif]-->
<!--[if IE 8 ]>    <html class="no-js ie8 ie" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <script src="../../../js/libs/modernizr-2.0.6-min.js"></script>

Also, notice I’ve included Modernizr. I make use of Modernizr on pretty much every project I work on. It allows me to feature detect with javascript and I can make some pretty cool fallbacks with that.

Once we’ve got that set up we can easily start fixing up IE.

IE specific CSS

.ie input{line-height: 35px;}
.ie input[type="email"]{color: #2F82C2;}
.ie input[type="password"]{color: #ED1C70;}
.ie label{right: 10px;}

.ie input[type="email"]:focus, .ie input[type="password"]:focus{
    background:transparent;
    -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#80ffffff,endColorstr=#80ffffff)";
    zoom: 1;
}
.ie7 label, .ie6 label{display: none;}

The CSS just makes things work in IE. Nothing special really. The weird -ms-filter is to add opacity to the background in IE.

Placeholder functionality fallback – jQuery with Modernizr

if(!Modernizr.input.placeholder) {
    $("input[placeholder]").each(function() {
        var placeholder = $(this).attr("placeholder");

        $(this).val(placeholder).focus(function() {
            if($(this).val() == placeholder) {
                $(this).val("")
            }
        }).blur(function() {
            if($(this).val() == "") {
                $(this).val(placeholder)
            }
        });
    });
}

This little snippet does the following:

  1. Detects for the placeholder attribute support. If no support is found, it continues
  2. It then looks for all input elements with the placeholder attribute
  3. It then takes the placeholder value and puts that within the ‘value’ attribute
  4. When focus is given to the element the value is set to none
  5. When blurred, if the value attribute isn’t nothing, it leaves the text alone
  6. If the value attribute is nothing, it replaces it with the placeholder text again

Foreseeable problems

The user can’t see the text if the input is full of characters.

True story, but the opacity of the label is so low that it doesn’t really interfere with the readability of the text itself. A way around this would be to add padding-right which covers the length of the label. The only downside to this would be the input field having to be very long.

In general I think this is fine, but if you’re very worried about this, I’d say add padding-right to the label and use icons instead of text. This will save a lot of space.

Conclusion

I think it’s a pretty solid technique that will leave your website visitors — or me at least — happier and less confused while logging in.

What say you?

  1. Dathan N says:

    Idk, seeing your demo, I’m dubious that it is a good idea to have text in the input background, what if the input text overlaps the bg text? I wouldn’t implement it like this.

    1. Jamy Golden says:

      Yeah, I agree – I did actually mention this in the article though.

      In this specific example the inputs are very large so it’s not really a problem, also if it does overlap it’s not really too noticable (in this example). However, in situations where you don’t have a lot of input space it’s probably a better idea to use an icon (with input padding to stop the text from overlapping) instead of text.

    2. alex says:

      A nice implementation might be to calculate the opacity of it based off the number of characters.

      For example, after the userr types in 5 or 10 characters or so, the user clearly knows what they need to type; so after that point fade it out. Or have it decrease with each character input.

    3. Jamy Golden says:

      Hey, that’s a really cool idea. The limit would need to change depending on the width/font-size of the field but yeah that could definitely work.

  2. Andre says:

    aah that’s awesome :-)

  3. Andy says:

    Good article, reflects alot of the practices I employ for web forms using HTML5. I have found the modernizr placeholder fallback to be troublesome, as the premise of the fallback is using the val attribute of the input for the Placeholder text. This causes me issues with validation and storing the info into a database.

    It is a nice fix, but causes me headache all the time!

    1. Jamy Golden says:

      Hey Andy,

      Yeah, using the placeholder as the value is definitely something to look out for! I would typically add simple javascript validation for !Modernizr.input.placeholder and check that the input fields should not be empty AND the values should not be equal to the placeholder attribute. That takes care of the “empty submit” problem.

  4. aykak says:

    This Is Good But remember as most of user still using IE6 & IE7 as you can find on installation of windows default browser version is 7 and this is looking ugly on IE6 & IE7 … but better for safari, firefox, …

    I have small sulotion as placeholder with javascript..

    it’s the same as placeholder but the only problem i have for this , it’s password field the enter text will be show up like hidden…

    but anyways… was good tutorial …

    thanks

  5. Arnoud says:

    I get it going in FF, Chrome… but not sure where to put the jQuery…

    Are you supposed to put that in new php file?

    Many thanks :)

    1. You can drop the jQuery wherever you want ( as long as it’s after the jQuery library has loaded ). You should be safe if you drop it off just before the closing </body> tag.

  6. Ali says:

    I’m using jQuery on my site, but i’m finding it can take a while to load. Now i tried minifying the scripts and running the site through a speedtest site and it had little impact. Is there any good way to compress images/css/js on the fly? or cache commonly used code?

    1. If you use the google CDN to load jQuery, chances are the person already has it in their cache so they won’t have to load it. Use scriptsrc to get your javascript library links.

      As for other images, css and javascript:
      Images – Use a sprite as often as you can
      CSS – Make sure you only have 1 css file and minify it, there’s not much more you can do with that.
      Javascript – I’d say minify and concatenate the javascript – I put all my plugins in plugins.js for example

    2. Ali says:

      Thanks for the advice, I lowered my image resolution and i combined my javascript as you suggested and it’s working a lot better now.

    3. aniartin says:

      i have the same problem..

    4. Jamy Golden says:

      You could always hide the form (with js) before anything happens and then show it again once the page has fully loaded.

  7. Remy Bach says:

    Wow! Nice job! I like the way you keep the slightly transparent version on the right hand side.

    I’ve created a jQuery plugin called superlabels (https://github.com/remybach/jQuery.superLabels) that has a very similar effect, and have recently attempted this using just CSS – looks like you beat me to it! :)

    1. Jamy Golden says:

      Thanks! Very cool and useful plugin. Yeah javascript is definitely necessary for a solid and equivalent cross-browser experience. I’d definitely progressively enhance and just use CSS for personal projects but companies aren’t /always/ as forgiving :) I’m sure I’ll use your plugin in future, thanks for the link.

  8. UnstoppableCarl says:

    It would be cool if it just showed the placeholder text slide from left to right with an animation instead of it being visible in 2 places.

    1. Jamy Golden says:

      Yeah, the visibility thing is just due to UX reasons. You could easily have it slide and fade to 0 opacity.

  9. lakshmikanth vallampati says:

    Hi,

    Your work is really nice… I like ti very much… The download button is not working properly… So can you please mail me the source files… to kanth.vallampati@gmail.com

  10. Dean says:

    Good stuff! The password field in IE still shows the placeholder text as ********* though. Any solutions for that?

  11. amit says:

    I don’t want to use js or jquery script for placeholder in my code. is there any trick through css> I mean to say if any solution where i just write css for placeholders and it works in IE…..THANKS

    1. Jamy Golden says:

      Unfortunately there isn’t a solid CSS replacement for the lte IE9s.