In-Field Labels: A Better Way + jQuery Plugin
Last week I was dealing with a unique problem. I needed to set focus to a username field, but the field had an in-field label. The script was set to clear out the helper text (label) when the user entered the field. Hmm…. that won’t work! I remember seeing a nicer implementation on Mobile Me for their login. Basically the label stays over the input element even after it had focus. Only after typing began did it totally disappear. Inspired by that implementation, today I am releasing the In-Field Labels jQuery Plugin so you can use this new method as well. The plugin is open source and available for download or on Github. If you can make it better, please fork it and send a pull request when you have finished your changes!
Benefits
- The input element or textarea never really has content, so validation can proceed without first checking for the field value.
- It uses standard markup for form elements
- It is under 1KB when minified and gzipped
- It takes one line of jQuery code to implement.
- The overlay can contain images and other HTML elements
- Its compatible with all modern browsers (And even IE6, the “not-so-modern” browser).
Issues
Like all in-field label implementations, this plugin still has problems when the browser tries to pre-fill the fields. When Safari and Firefox pre-fills the fields for the user, it never sends a “change” event to hook into. You can get around this by adding autocomplete=”off” to the input elements, but this is undesirable for longer forms. I am looking for a fix, but for now, this plugin is still usable for shorter forms!
Quick Overview
The effect is achieved by overlaying the label element over the input, password, or textarea and making it semi-transparent when the field has focus. Once a keystroke is detected the label disappears entirely until the field loses focus. If it is empty on blur, then the label fades back in. Clicking on the label auto sets focus on the field.
Download It
Head over to the Sample Page to read more about the plugin and to download it. Let me know your thoughts and suggestions in the comments below!
Doug Neiner is an Editor at Fuel Your Coding and is president of Pixel Graphic Design Studio. He is addicted to new technology, and specifically loves spending time with WordPress, Ruby on Rails and jQuery. Learn more via twitter or his Google Profile.






Interestingly the sample page has a (minor) bug which isn’t present on the blog’s “leave a comment” form. In the sample page you can select some of the text of the label, and this then inhibits the fade and selection setting.
Arguably this is wanted behavior, but since tabbing doesn’t highlight the label text one could argue that for consistency it shouldn’t be selectable either.
Anyway, a very nice little plug-in which I shall be looking to use. Thanks!
Great point… totally missed that! I will disable selection of the label in my next update. That and graceful degradation should make the plugin more useful.
Great plugin Doug!
I love how small it is which lends to readability and performance. But hey, what’s with this IE6 support?? Get that outta here! (j/k, kind of)
The browser auto-complete issue is a bummer, I’m interested to see if anybody knows of a workaround that doesn’t involve disabling auto-complete altogether.
Very nice, I like the subtle fade on focus.
The only issue I can see is graceful degredation. With javascript disabled, the label is still positioned directly over the text field (thanks to the css), but never disappears, so you can’t really see what you’re typing in.
Perhaps you could apply the absolute positioning css via javascript, such that if javascript is disabled the label is not positioned directly over the textfield, but instead above it in the page flow.
Evan, you are totally right. I let my excitement to publish force me to leave that off. I have to solutions in mind I plan on implementing. 1) Is to add a class to the label’s parent after the script initializes. Requiring that class and associated position:absolute to be in the CSS. 2) Is just add position: absolute to the label when the script is run. I plan on it being an option like: noScript: “classname” or true for adding position:absolute automatically.
What do you think?
If you ask me…
I would prefer your first (1st) propositions. Keeping everything within your plugin, even the associated CSS declarations.
Just make it short and clean so it would be easy for us to overrule your top & left label positionning according to our needs (if font-size differs).
Something like:
Interesting. I wrote a plugin for just this purpose a few months ago (which I never ended up using).
Also…I ran into the same dreaded autofill issue as you. I actually *did* come up with a solution for it. I posted the solution as well as the plugin code on my blog, here: http://furrybrains.com/2009/01/02/capturing-autofill-as-a-change-event/
Have a look and see if that solves your problem? You might be able to modify that code as well if it doesn’t suit your purposes, but perhaps the gist of it will work.
Please do let me know if you have any questions about it (although 6 months ago is an eternity for me as far as my code memory goes…).
Thanks for sharing… I am going to look at it in more detail later. I wanted to avoid polling if at all possible, but it seems that is what is going to have to happen. Certain use cases, such as a login box or search field should probably have autocomplete=”off” anyway for usability. But for slightly longer forms this is a real issue. Thanks again!
I hear you. I wanted so badly to find an alternative to polling myself. I’ll keep an eye on what you do; I’d be especially be interested if you find a way around polling.
my one nitpick/suggestion is to initialize the css (positioning of the labels etc…) via js; so if the user — for whatever reason — had js disabled, or worse yet the js didn’t load — the label would still be visible/available.
Another similar issue to the one described in the article happens when you drag and drop some text from the page into the input, there’s no “change” event as well. Tested in FF2, FF3 and FF3.5.
Why does everyone insist on absolutely positioning labels over the top of inputs. Why not just use the actual input and fill it with your label (as a value); then change colours as you see fit; i.e. using the focus/blur events.
Hey James. The only way I used to accomplish this was just as you described, swap the values in and out, etc. I ran into these problems that made me feel it was inferior to absolutely positioned labels:
1) Validation: Now in addition to checking if a field was populated/ prior to submission, I had to check if what it was populated with was the label text or a real value. If I didn’t do client-side validation, or somehow the form got submitted early, the server would now have to check for those same values.
2) Password Fields: You can’t “swap” out label text as the value of a password field. Some browsers support changing input.type, others don’t. Once a while back, I created a script that swapped out a hidden “Password” plain text field with the real-one on focus. That is unnecessary with labels overlaid on the field.
3) No Remaining Feedback: Once the field was entered, the label was gone. I have more than once clicked in a field, had the label disappear, and forgot what it was. Had to click out (heaven forbid the label didn’t come back) just to see what the field was. Leaving the label still visible allows the user to click, collect their thoughts, and still see what the field is. (I have a use case where I had a hidden login form. The user clicks “login”, and the form pops up. I wanted to save the extra click, so I needed to set focus to the username field. If I used the swapped out method, the field would be blank and inexperienced users would have to guess what field they were in. )
4) Change Tests: The tests on whether or not to show/hide a label is now simply decided if the field is empty, not whether the field has/doesn’t have the specific label value associated with the field.
Anyway, love the work you do with jQuery and am really happy you stopped by to comment. Thanks!
Thank you for the reply Douglas.
1) You can stop it from ever getting to the server by attaching a “submit” event handler to the form; and then, if the current value is the same as the label text you could return false, thus preventing any default action (i.e. form submission).
2) Good point. Although you don’t always have to spell out “password” for users to know what it is; a field filled with “*****” is quite obviously a password field. There is room for improvement though and I feel your solution may be a step closer.
3) Technically you don’t have to empty the field on the “focus” event; you could use the “keydown” or “keypress” event to wait for the very first character to be typed. Doing this would produce the same effect you’ve got with your solution.
4) Not sure what you mean here. I’m pretty confident any conditions you’re currently testing for can be reproduced without having to have an “overlay” label element.
There is an usability issue with your solution as well. If I want to paste some text in the field I right click on the area and press paste but, with your demo, there is no “paste” option because I’m really right-clicking on a regular element (the overlay), not the input element.
This is a really cool plug-in. Any ideas on how to make this work for a select element ?
Wow! I was about 5 mins before writing a simpler version of this on my own… but this just does everything I need! Thank you :)
I second the mod for working with select elements. If you have a form that utilizes a number of them, it’s almost not worth using the script because half your form still has labels…kind of a continuity issue. I know most selects already have text showing due to a preselected index but that can easily be made blank…
Very good plugin Douglas. It address most of my requirements.
About James arguments… I’m not an advance JS developper but he may have a point. I know his approach is consistent with the technic proposed by Mike Brittain in the “Making Compact Forms More Accessible” article on A List Apart.
http://www.alistapart.com/articles/makingcompactformsmoreaccessible/
This plugin is great. Have you found any workarounds for the autocomplete issue?
I encountered an issue applying inFieldLabels to an input that didn’t have the type attribute set. Text is the default fallback so this shouldn’t matter. To fix this I suggest you change the selector to the jQuery shorthand version:
from:
“input#” + for_attr + “[type='text'],” +
to:
“input#” + for_attr + “:text,” +
Thanks for this plugin. I had noticed Apple’s subtle treatment of the input placeholder text upon focus, nice to see it so easy to implement. A nice extension of this would be to add support for the placeholder attribute if the users browser doesn’t already support it:
The url I included in my previous comment about the placeholder attribute was eaten: http://diveintohtml5.org/forms.html
Is it possible to make a version without animating opacity, just show/hide?