CSSKarma

display your <style>

designing the web since 2002

Form Design with Sliding Labels

Sliding Label banner

Please use version 3 of sliding labels with updated options and bug fixes at: http://www.csskarma.com/blog/sliding-labels-plugin/

A few weeks ago I was reading an article on form UI by Luke Wroblewski of Yahoo!. For those who aren’t familiar with Luke, he (quite literally) wrote the book on good form design.

In the article, one certain section about placing labels inside of form fields stood out to me:

Because labels within fields need to go away when people are entering their answer into an input field, the context for the answer is gone. So if you suddenly forget what question you’re answering, tough luck—the label is nowhere to be found. As such, labels within inputs aren’t a good solution for long or even medium-length forms. When you’re done filling in the form, all the labels are gone! That makes it a bit hard to go back and check your answers. Luke Wroblewski

He brings up a good point. Generally speaking, you can look at a field that says “Tim Wright” and know that it was a field for your (my) name. But for long forms, yea, I do agree that you can forget some of the questions you answered.

For best practice, Luke talks about leaving your labels outside the form field so it’s always available to the user. I do think it’s a pretty good solution, but I think we can get a little more creative than that.

Enter: Sliding Labels

After reading that article it occurred to me that there’s no reason we can’t have the best of both worlds. I like how inline labels look, and I see Luke’s point about them disappearing as you fill out the form. But, we have jQuery, we know about progressive enhancement, and we have creative minds, so let’s build something that allows us to keep the label inline, but slide it off to the left (or up, whichever you prefer) rather than going away on click.

View demo (version 2)

The HTML

<form action="" method="post" id="info">
   <h2>Contact Information</h2>
   <div id="name-wrap" class="slider">
      <label for="name">Name</label>
      <input type="text" id="name" name="name">
   </div><!--/#name-wrap-->

   <div id="email-wrap"  class="slider">
      <label for="email">E&ndash;mail</label>
      <input type="text" id="email" name="email">
   </div><!--/#email-wrap-->

   <div id="street-wrap"  class="slider">
      <label for="st">Street</label>
      <input type="text" id="st" name="st">
   </div><!--/#street-wrap-->

   <div id="city-wrap"  class="slider">
      <label for="city">City &amp; State</label>
      <input type="text" id="city" name="city">
   </div><!--/#city-wrap-->

   <div id="zip-wrap"  class="slider">
      <label for="zip">Zip code</label>
      <input type="text" id="zip" name="zip">
   </div><!--/#zip-wrap-->

   <input type="submit" id="btn" name="btn" value="submit">
</form>

The only necessary items to make sliding labels (as I built it) work are the wrapper element (DIV in my case) and applying a class of “slider” to it (you can change this easily in the JavaScript).

At this point we have a pretty basic, and ugly form

slidinglabels no css

The CSS

body                       { font:12px/1.3 Arial, Sans-serif; }
form                       { width:380px;padding:0 90px 20px;margin:auto;background:#f7f7f7;border:1px solid #ddd; }
div                        { clear:both;position:relative;margin:0 0 10px; }
label                      { cursor:pointer;display:block; }
input[type="text"]         { width:300px;border:1px solid #999;padding:5px;-moz-border-radius:4px; }
input[type="text"]:focus   { border-color:#777; }
input[name="zip"]          { width:150px; }

/* submit button */
input[type="submit"]       { cursor:pointer;border:1px solid #999;padding:5px;-moz-border-radius:4px;background:#eee; }
input[type="submit"]:hover,
input[type="submit"]:focus { border-color:#333;background:#ddd; }
input[type="submit"]:active{ margin-top:1px; }

The only 100% necessary CSS in there is the position:relative on the wrapper element (DIV). The rest is basically cosmetic and you can mess with it as you see fit.

At this point you should have a pretty normal looking form with labels on top of their respective inputs.

labelslider no js

The jQuery

Now for the section everyone skipped to, provided you didn’t go straight to the demo (which I usually do).

$(function(){
$('form#info .slider label').each(function(){
	var labelColor = '#999';
	var restingPosition = '5px';

	// style the label with JS for progressive enhancement
	$(this).css({
		'color' : labelColor,
		 	'position' : 'absolute',
	 		'top' : '6px',
			'left' : restingPosition,
			'display' : 'inline',
    	               'z-index' : '99'
	});

	// grab the input value
	var inputval = $(this).next('input').val();

	// grab the label width, then add 5 pixels to it
	var labelwidth = $(this).width();
	var labelmove = labelwidth + 5;

	//onload, check if a field is filled out, if so, move the label out of the way
	if(inputval !== ''){
		$(this).stop().animate({ 'left':'-'+labelmove }, 1);
	}    	

	// if the input is empty on focus move the label to the left
	// if it's empty on blur, move it back
	$('input').focus(function(){
		var label = $(this).prev('label');
		var width = $(label).width();
		var adjust = width + 5;
		var value = $(this).val();

		if(value == ''){
			label.stop().animate({ 'left':'-'+adjust }, 'fast');
		} else {
			label.css({ 'left':'-'+adjust });
		}
	}).blur(function(){
		var label = $(this).prev('label');
		var value = $(this).val();
		if(value == ''){
			label.stop().animate({ 'left':restingPosition }, 'fast');
		}
	});
})
});

At this point, you should have a fully working sliding label form!

labelslider final

View demo (version 2)

Making sure everything is still usable without JavaScript is important (no matter what people say), it’s just a basic principle of progressive enhancement. Believe it or not, there are still people browsing without JavaScript (blackberry users – turned off by default). So creating the interaction in layers, as we did, will help it be past-proof.

Try it out and let me know what you think. So far I’ve used it on a password change form, so definitely let me know if you find a place to use it!

Tags: , , ,

You can leave a response, or trackback from your own site.

« Older Comments | Newer Comments »

Comments (107)

  1. Jay Tillery says:

    Clever effect. I’ll be using this in a new design this week.

  2. It doesn’t appear to work properly when tabbing through the fields or when fields have been auto-populated by the browser (on Safari – don’t know about other browsers behavior).

  3. David Simmer says:

    I did this a while back (pre-jQuery): http://simmerdesigns.com/curious/ and wrote it up a bit

    It’s a good UI principle, and jQuery can’t be beat for speeding up development of useful UI features.

  4. josh says:

    One problem I immediately found was that when my autofill feature kicks in it populates the fields but the labels stay, so I have my information with labeles overlapping on top of them. i suppose this is becasue the autofilll doesn’t make the fields “active” thus sliding them out. Still very cool though

  5. Hung Bui says:

    WOW, very nice jQuery effect. This would definitely a nice feature to have on the web.

    Thanks for sharing this.

  6. Steve says:

    Hi

    This is just great. I have been playing with this for a few days now. My aim was to replicate the one used on the mobile me login whete the lable fades slightly but this is just right.

    I am now trying to amend the code to incorporate a text field on a contact form but can’t seem to get the label to move. Replicating the code with modified variables doesn’t work.

    Any ideas?

    Steve

  7. Steve says:

    Please ignore my previous ramblings as I have jsut read the 2 posts explaining how this is achieved.

    Many thanks

    Steve

  8. Jason says:

    Thanks for the excellent tutorial. Is this code under the GPL? Can I use it for my website?

  9. mas73 says:

    Very cool effect! It’s an attention grabber. Practical enough to keep a person’s attention to what they’re typing. So I likes the creativity!!

  10. Mother of Pearl Beads says:

    Great blog!i really enjoyed reading your posts.i’ve also bookmarked your feed to stay in touch with your news.

  11. Jim says:

    I am getting an error where the label text slides way to far.
    In fact it seem like instead of moving the label width plus 5, it moves the input field width plus 5… cant work out why ?

    • Tim says:

      Are you using any padding on the label? That can throw off the width. Try putting a background color on it and see how it looks.

      • Jim says:

        Thanks Tim,
        There was no padding on the label, but the trick of adding a colour background showed me that there must be something making the labels bigger. Sure enough a containing div had the label width set to 280 !
        All sorted
        Thanks again.
        Jim

  12. Eirik says:

    This is sweet, thanks for sharing!

  13. William Besson Beats says:

    Took me time to read all the comments, but I really enjoyed the article. It proved to be Very helpful to me and I am sure to all the commenters here! It’s always nice when you can not only be informed, but also entertained! I’m sure you had fun writing thx

  14. This is shockingly beautiful to me. So much CSS junks up the usefulness of forms; this doesn’t. Thank you!

  15. Jim says:

    Just a thought, it would nice to be able to animate this differently depending on which label is in focus. I have tried this by doing…

    if(value == ''){
    			if(label == 'captcha'){
    			label.stop().animate({ 'left':'-'+20 }, 'fast');
    			}
    			else {label.stop().animate({ 'left':'-'+adjust }, 'fast');}
    
    		} else {
    			label.css({ 'left':'-'+adjust});
    }

    But it always defaults to the later animation. I know it has something to do with
    if(label == ‘captcha’)
    but not sure what I should put instead
    ??

    Jim

    • Tim says:

      That should work if you save the label text “captcha” as a variable. Something like this:

      var captcha = $('label#captcha').text();

      Also add the ID of “captcha” to the appropriate label

    • Tim says:

      and remove the quotes

      • Jim says:

        Thanks Tim,
        I tried this…

        
        	$('input,textarea').focus(function(){
        	    var captcha = $('label#captcha').text();
        		var label = $(this).prev('label');
        		var width = $(label).width();
        		var adjust = width + 5;
        		var adjust2 = width + 20;
        		var value = $(this).val();
        
        		if(value == ''){
                if(label == captcha){
                label.stop().animate({ 'left':'-'+adjust2 }, 'fast');
                }
                else {label.stop().animate({ 'left':'-'+adjust }, 'fast');}
        
               } else {
               label.css({ 'left':'-'+adjust});
               }
        

        And it still defaults to the else statement

        For the label i have

        Enter Code

        What am i missing ?

        Thanks for taking the time to look at it :)

        Jim

      • Jim says:

        ooooh it wont let me enter label code but I put the id=”captcha” in :)

  16. It’s one of the greatest ideas I’ve seen on UX

  17. iMaxEst says:

    Nice effect. How about textarea? I,m just putting (‘input,textarea’) instead of (‘input’), but textarea lable in this case is located in the previous input field, just over that fiel lable. How to correct?

  18. Dak says:

    Have you tested this with textarea’s? It doesn’t seem to work with that type of input although I haven’t tried debugging it yet.

  19. Jani Forsey says:

    Nice article, lots of useful information. Thanks

  20. Fabian says:

    Very creative! I like it.

  21. Tachyon says:

    What about a textarea?

  22. 3kkl says:

    oh, this is a neat idea! although it’s not useful for making forms take less space in contrast to the original idea of inline labels, since you still have to preserve the extra space for the sliding label. you can also use the title attribute or any other “onhover” method to display labels. very cool effect anyways!

  23. Kai Nehm says:

    creative approach, but you lost on Safari/Mac with auto-fill (which is enabled by default)

    The first label slides, and the rest gets filled in a very ugly manner and editing doesn’t make it better :(

  24. Steve Holden says:

    I hope this doesn’t seem too negative, but since there’s room outside the fields for the labels, why not just put them there in the first place?

  25. This is really helpful information, thanks.

  26. Max says:

    very usefull.. love it

  27. Martin says:

    Your approach to labels is very innovative, but I think the animation can be distracting.

    Btw, I’ve been looking for the perfect jquery inline-label plugin but I can’t find anything like this implementation, made with the Prototype framework:
    https://launchpad.37signals.com/signin

    This one is so good. If someone is able to recreate it with jQuery, many people would be grateful :)

« Older Comments | Newer Comments »

Trackbacks & Pingbacks (33)

Leave a Reply

New from the blog

Are My Sites Up? authenticjobs.com