Grow your CSS skills. Land your dream job.

Float Labels with CSS

Published by Chris Coyier

You've probably seen this pattern going around. It's an input that appears as if it has placeholder text in it, but when you click/tap into that input, that text moves out of the way and allows you to type there. It's rather clever, I think. Brad Frost has a really good post on it, detailing the pros and cons and such.

Many of the demos I've seen involve JavaScript. The other day I was checking out at Nest.com, saw their technique for it, and I thought of a way I could pull that off without JavaScript. So here we are.

Here's how the Nest.com one looks:

And here's my take:

See the Pen Label Pattern with just CSS by Chris Coyier (@chriscoyier) on CodePen.

It's not quite as sexy as the Nest ones, where the text is fading out as the label is sliding up. Certainly possible with some JavaScript, but we're going to stick with pure CSS here. Still might be possible though. I'll leave that challenge up to you.

Some Quick Reminders

There are two reasons you might consider doing this:

  1. It might be able to save space. Because the input and label are combined, it takes up less space. When an input is in focus, you do still need to show both the label and input, but you can get that space by either using some of the space the input was already using, or by growing the area temporarily only for the focused input.
  2. It makes the input one big button. Not that inputs aren't already, and not that labels aren't when they have a proper for attribute, but there is something kinda nice about a big rectangle that tells you what it wants that you click/tap. Might make for a nice experience particularly on mobile.

I'd say, generally, that always-visible labels are probably "better" - but this is a clever idea and done right, may be useful occasionally. There is always a risk of screwing this up and hurting accessibility too, so take care. One downside to this pattern: we can't use placeholder in addition to the label, which can be helpful (e.g. a label of "Phone Number" and a placeholder hint of "(555) 555-5555").

The Trick (1 of 3) - The label is the placeholder

There is a <div> that contains both the <label> and <input> (which you need to do anyway because inputs within forms need to be in block level elements) that has relative positioning. That allows absolute positioning within it, which means we can position the label and input on top of each other. If we do that with the input on top, but with a transparent background, you'll be able to see the label right underneath it while still being able click into it.

  <div>
    <input id="name" name="name" type="text" required>
    <label for="name">Your Name</label>
  </div>
form > div {
  position: relative;
}
form > div > label {
  position: absolute;
}

The Trick (2 of 3) - the :focus state and the adjacent sibling combinator

The source order of the <label> and <input> wouldn't matter much here, since semantically they are tied together with the for attribute. But if we put the input first, that means we can leverage its :focus state and an adjacent sibling combinator (+) to affect the label when it is focused. Similar in concept to the checkbox hack.

input:focus + label {
  /* do something with the label */
}

You can do whatever you want with the label. Just find a cool place to move it and style it that is out of the way of typing in the input. My example had two possibilities: one was making it smaller and moving toward the bottom of the input, the other was moving it to the far right side.

form.go-bottom label {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  transition: 0.2s;
}
form.go-bottom input:focus + label
  top: 100%;
  margin-top: -16px;
}

The Trick (3 of 3) - the :valid state

Once there is actual text in the input, and the input goes back out of focus, it would be very weird (bad) to see the label and the input text on top of each other. Fortunately in CSS there is a :valid selector that works on inputs when they are in a valid state. That valid state can be "any text at all", assuming the only thing that makes it valid is having any value at all, which can be achieved like:

<input type="text" required>

Then remember the only reason you could see the label at all was because the input has a transparent background. To hide it, we can use an opaque background instead:

form input:valid {
  background: white;
}

The rest of this is just fiddling around with design details until you have it just how you like it.

More

The idea originally came from Matt D. Smith, with this design:

Comments

  1. AWESOMENESS!!!

    That’s really impressive… if only it was fully supported on all browsers

    • Permalink to comment#

      That can be said about pretty much any relatively new CSS features!

      That being said, this is a pretty good addition to placeholder text.
      Even if it doesn’t work, no harm done.

  2. Alex
    Permalink to comment#

    Nice! One note: instead of overloading :valid, which you might want to use for field validation, you can use the :empty selector…

    • Rene Poulsen
      Permalink to comment#

      Alex, I don’t think the :empty selector would work in this case. Doesn’t the :empty selector just select an element with no child elements? In this case we need to check for the value of the input field – and not if it has any child elements.

    • Inputs are apparently always considered :empty – http://codepen.io/chriscoyier/pen/oiKwD

    • Permalink to comment#

      The thing is, input elements are ‘empty’ elements according to the HTML spec, (just like images are) so they can never have any child nodes.

  3. scheme
    Permalink to comment#

    Even without the effects this is a better approach than using placeholders as labels, as these have totally different semantics and shouldn’t be used as such.

    https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-placeholder

  4. Permalink to comment#

    I made a [Similar Sample]((http://codepen.io/Wakkos/pen/hCquc) to visually “validate” (Emotional Validation =P) but I found a problem: I (We all) need a not[:focus]:invalid-input-but-not-empty selector to make beautiful things with this.

    Since I tried to give a color when the user inputs an invalid text but gets the focus out of the field =(

  5. Todd
    Permalink to comment#

    This is awesome!
    It would be nice if there was a CSS selector that recognised the relation between the input and label elements. So we might say something like input:focus:label. This would probably allow for even more creativeness, because we don’t need the label immediately after the input in the DOM. Just a thought.

  6. Permalink to comment#

    Pure awesomeness. Think I might use this on a new web-project I am doing for a client.
    Thank you very much.

  7. I actually made a pen about this not long ago!

    It’s still a well-thought, awesome concept.

  8. Will B.
    Permalink to comment#

    One thing I like about Matt’s (the original you indicated you based your version on) is that the field label still exists after you leave the field. Is there any way to maintain the visual label with yours. I really like the behavior. I also really like that there’s no JS involved.

  9. Permalink to comment#

    Is it me or is it just TO sexy?

  10. Rachel
    Permalink to comment#

    It’s a nice trick and I had a go at doing something similar though adding a z-index to the input and using the focused state of the input so that the label can still be placed in an accessible way. It’s a shame that the trick requires all the fields to be required for it to work.

  11. Jaap
    Permalink to comment#

    What also would be nice, is to put some extra validation in this way. This way, all is kept in the same input field.

  12. Permalink to comment#

    Yep… I am using this now, thank you.

  13. What really excites me here is the use of the adjacent sibling selector. I am, however, ashamed to say that I haven’t been using this selector at all. That’s about to change.

    • Claudiu
      Permalink to comment#

      Even if you haven’t heared of them, you can tell Adjacent sibling selectors have been around for a while when you see Browser compatibility – IE7. Lol. Jokes aside, they are very useful! I wish you good luck! ;)

  14. Zach D.
    Permalink to comment#

    For the labels on the right, a padding-right on the input:focus and textarea:focus greater than or equal to the width of the label (40% in the demo) keeps your input from going underneath the label as you type.

    The tradeoff is when manually setting your caret with a click, the padding changes after focus but before the click sets the caret, so it’s a bit unpredictable.

    (On codepen: Label Pattern with just CSS + padding-right)

  15. Felipe (@LFeh)
    Permalink to comment#

    Nice, nice and nice!

  16. In a single word, “AWESOME”

  17. Vesa Piittinen
    Permalink to comment#

    Had some fun with this. The complex one is what makes more browsers fail, like Opera Presto.

    http://codepen.io/Merri/full/boDgs

  18. Eric Young
    Permalink to comment#

    That is a very cool form concept.

  19. RogueSkolar
    Permalink to comment#

    Definitely incorporating this into current project. Very, very nice!!

    Also big props to Jeremy Gillick up above for linking to his original post.
    What I really liked was how he touches on usability when the fields are in focused state. Totally never occurred to me. At all! Real nice.

  20. Louwki
    Permalink to comment#

    Very cool !

  21. pradeep
    Permalink to comment#

    Nice! let me know how to show form validation here?

  22. Permalink to comment#

    Nice. Thank You.

  23. I made a mailchimp sign up form with validation here: http://mattdsmith.com/float-label-demo/ Thanks for the write up Chris!

  24. Permalink to comment#

    I would update this a little bit to display labels by default if a browser that does not support placeholders (IE 8/9):

    input:focus + label,
    html.no-placeholder input + label
    {
        top: 100%;
        margin-top: -16px;
    }
    

    And some jQuery based JavaScript which should be converted to pure JavaScript or added to your Modernizr tests:

    $( ‘html’ ).addClass( ‘placeholder’ in document.createElement( ‘input’ ) ? ‘placeholder’ : ‘no-placeholder’ );

  25. Michael
    Permalink to comment#

    I would like to see how the select label works with this. I would expect that the vertical-shift would have to be off of the arrow and the right-shift would have to cover the arrow.

  26. Permalink to comment#

    Chris, you did it again.
    Looks like I’ll have to update my Drupal module to use this latest and greatest: Label Trash module

  27. Permalink to comment#

    This is awesome. I can’t wait to use this in my next project.

  28. skycode
    Permalink to comment#

    Great, but it is not so prety in ie8 below

  29. Permalink to comment#

    This is awesome!

    I’ve also made a implement of this , and add the validation (status) by highlighting the label above. My concept is different: The label is required for input semantically.

    Check it out and let me know your thoughts.

  30. Sinled
    Permalink to comment#

    Tried such approach some time ago, it has problem with when field not empty but invalid:

    Screen

  31. Jeremy S
    Permalink to comment#

    You could still use placeholders if you’re able to move the label out of the way. Not sure how that would look though.

    Another option is to “hide” the placeholders until you focus on the field — http://codepen.io/zaus/pen/gKnhl

  32. Permalink to comment#

    Great article Chris. Inspired me to create a bootstrap implementation and a remix of the look and feel. Check it out at my blog: http://mattlambert.ca/blog/animate-bootstrap-form-labels-using-css3-transitions/

  33. Subash
    Permalink to comment#

    Thank you! Very informative. Keep up the good work!

  34. Genius. What a great way of creating a new experience for forms. It’s nice touches like this that make all the difference.

  35. Permalink to comment#

    This is clever. But I must save the animation distract the typing a little bit. Other than that, its great way to reduce the space and make the form looks modern.

  36. This is a pretty neat idea. A lot of things have been getting dressed up over the years with CSS3 and jQuery, but forms have been mostly ignored… probably cause most people hate making forms :P. I like how this saves space and adds a bit of coolness to forms. I may implement it for a current project just to dress up my otherwise boring contact form. IE8 compatibility is a concern, but with the \9 css trick, I think this concept is feasible. Might make a little form framework in the near future. Thanks.

  37. Permalink to comment#

    How did you make those animated images in which you show how the forms work?

  38. Marco
    Permalink to comment#

    i think it would be bad for usability if the label is lost after it has some information in it, so i would also add a rule so that it keeps visible with the :valid state from the input.

  39. Chris B
    Permalink to comment#

    I am having and issue with Firefox and IE. The labels are not lining up in the input, they are off to the right of it. Looks great in Chrome, Safari, and Opera though. Has anyone come across this or is it just me?

  40. Permalink to comment#

    perfect if color label change when field is valid

    like here http://caldev.io/a with icon status (asterix or check)
    powered by angularjs

  41. jzilg
    Permalink to comment#

    I’ve created a Form just like the last example.

    http://codepen.io/jzilg/full/mujzo

  42. Pratik
    Permalink to comment#

    quite amazing

  43. Vigorous and Awesome. Work well in Firefox , but when adsense ads comes its disappears ( as per ad width ). I will be more thank full if you can give solution for this. Thanks in Advance & waiting for your reply.

  44. Alex
    Permalink to comment#

    I’m wondering how come no one mentioned non-input UI elements. How do you apply this to selects, ckeckboxes, radios, autocompletes etc.

    Because without full UI support this is just a prototype idea. IMHO, it is not okay to have some UI patterns on textfields, but not other types.

  45. PJ
    Permalink to comment#

    This is lovely, but I am having the same issue Chris B. above is. The labels are just off the right of the boxes, and nothing happens on focus except the border color change. This is in a file with nothing but the code copied from this css-tricks example for both form and style. I then changed my doctype etc. to html5 thinking it might be something not handled by previous versions, but apparently it’s not that.

    I would hugely appreciate any advice. I’ve not done very much with CSS so far besides basics (though I’ve been coding as a hobby for years) but usually when I use someone’s example plainly and nothing else, it works.

  46. PJ
    Permalink to comment#

    To add: Jeremy S’s version puts a placeholder in the box, which ‘vanishes’ upon focus, but it still does not bring up the label at the bottom of the box (in any browser). You guys are sure there is not some required head tag or javascript for the page for this to function, that maybe you’re assuming is obvious?

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".