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:
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:
- 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.
- 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 and wouldn’t matter much here, since semantically they are tied together with the
for
attributeBut 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:
- Remember to read Brad Frost’s article that covers the pros and cons well.
- A number of people have tackled this with JavaScript: Jeremy Fields, Jim Nielsen, and maman
- As I was looking around for links to put down here, I discovered David Bushell did just about exactly what I’ve done here.
- Here’s a collection of Float Label examples on CodePen.
:placeholder-shown
Update 2018 – Using The :placeholder-shown
selector didn’t exist when this article was originally written. Emil Björklund revisists the topic now that it does.
AWESOMENESS!!!
That’s really impressive… if only it was fully supported on all browsers
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.
Nice! One note: instead of overloading
:valid
, which you might want to use for field validation, you can use the:empty
selector…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
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.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
Yea, that was my first thought as well.
Jonathan Snook was quicker – http://snook.ca/archives/html_and_css/floated-label-pattern-css
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 =(
This is awesome!
It would be nice if there was a CSS selector that recognised the relation between the
input
andlabel
elements. So we might say something likeinput:focus:label
. This would probably allow for even more creativeness, because we don’t need thelabel
immediately after theinput
in the DOM. Just a thought.Pure awesomeness. Think I might use this on a new web-project I am doing for a client.
Thank you very much.
I actually made a pen about this not long ago!
It’s still a well-thought, awesome concept.
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.
Is it me or is it just TO sexy?
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.
What also would be nice, is to put some extra validation in this way. This way, all is kept in the same input field.
Yep… I am using this now, thank you.
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.
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! ;)
For the labels on the right, a
padding-right
on theinput:focus
andtextarea: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)
Nice, nice and nice!
In a single word, “AWESOME”
Had some fun with this. The complex one is what makes more browsers fail, like Opera Presto.
http://codepen.io/Merri/full/boDgs
Hi, I’m the developer behind Nest’s version of float labels. I’m glad you liked it! Shortly before it went to production I posted about how I did it with sample code and stripped down demo. I was also unhappy with it requiring JavaScript and have worked on a similar CSS only approach that will hopefully be going to the site soon. The original post: http://mozmonkey.com/2013/12/good-ux-for-placeholders-as-field-labels/
That is a very cool form concept.
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.
Very cool !
Nice! let me know how to show form validation here?
I’d love to see a demo on that. Since the main point of this technique is space-saving, I’d guess you’d have to get clever with where you add the error messages such that it’s 1) obvious 2) easy to understand 3) still space economical
Styled tool tips wouldn’t be too hard.
The Nest forms show errors by creating a floating red bubble above the field. I’ve created a simple example on codepen:
http://codepen.io/jgillick/pen/JKwlq?asdfasdf
Nice. Thank You.
I made a mailchimp sign up form with validation here: http://mattdsmith.com/float-label-demo/ Thanks for the write up Chris!
I would update this a little bit to display labels by default if a browser that does not support placeholders (IE 8/9):
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’ );
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.
Chris, you did it again.
Looks like I’ll have to update my Drupal module to use this latest and greatest: Label Trash module
This is awesome. I can’t wait to use this in my next project.
Great, but it is not so prety in ie8 below
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.
Tried such approach some time ago, it has problem with when field not empty but invalid:
Screen
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
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/
Thank you! Very informative. Keep up the good work!
Genius. What a great way of creating a new experience for forms. It’s nice touches like this that make all the difference.
Hm.. I don’t get it.. The slide in from bottom effect can also be achieved with pure CSS. (keyframe animation)… http://codepen.io/pixelass/pen/nujKD
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.
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.
How did you make those animated images in which you show how the forms work?
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 theinput
.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?
perfect if color label change when field is valid
like here http://caldev.io/a with icon status (asterix or check)
powered by angularjs
I’ve created a Form just like the last example.
http://codepen.io/jzilg/full/mujzo
quite amazing
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.
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.
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.
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?