Here is a cool way to make the placeholders "become" labels as the input receives focus.
Here is a pen with the final result.
First, you have to put the label
AFTER the input
in the HTML.
<form action="">
<input type="text" id="fullName" name="fullName">
<label for="fullName">Full Name</label>
</form>
This will ensure that we can target the label
with our CSS.
Then, instead of giving the input
a placeholder
directly in the HTML, we will use our label
as the placeholder. In order for the label
to be inside the input
, we can use transform: translate()
. We can also use a lighter color to really make it look like a native placeholder.
Here is the relevant CSS for the initial state (the values used for the translation can vary depending on font size, positioning, etc.).
label {
color: #999;
transform: translate(0.25rem, -1.5rem);
transition: all 0.2s ease-out;
}
Now, to position it on top of the text when the input
is in focus, use the following.
input:focus + label {
color: #111;
transform: translate(0, -2.75rem);
}
It works!
But we still have a problem. The styles are are only applied to the label
when the input
is in focus. This means that if you type something in the input
then focus elsewhere, the label
will come back to it's original position.
To fix this, we will have to use the :placeholder-shown
selector. This selector allows to style an element whenever an input
's placeholder
is, well, shown. In our case, we actually want to style the label
when the placeholder
is NOT shown, so we will also have to use the :not()
selector. Finally, for this to work, your input
has to have a placeholder. Since we want to use our label
as the placeholder
text, we can simply write an empty space as the placeholder
value (an empty string ""
will not work).
<form action="">
<input type="text" id="fullName" name="fullName" placeholder=" ">
<label for="fullName">Full Name</label>
</form>
input:focus + label,
input:not(:placeholder-shown) + label {
color: #111;
transform: translate(0, -2.75rem);
}
Now everything works like we want it to.
The :placeholder-shown
selector is relatively new, but browser support is pretty good. The only browser to not recognize it is Edge. To remedy this, we can use a @supports
query hack to check if the code is run in Edge (you can find more hacks like this at http://browserhacks.com/).
Usually, this hack is used write code that is only supported in Edge. Since we want the opposite, we can add not
in front of the condition of the query.
We should also apply the final position to the label
before anything else. This way, the Edge browser will display the labels on top of the inputs like a normal form, and the other browsers will apply the 'placeholder' styling to it.
label {
display: block;
transform: translate(0, -2.75rem);
}
@supports (not (-ms-ime-align:auto)) {
label {
color: #999;
transform: translate(0.25rem, -1.5rem);
transition: all 0.2s ease-out;
}
input:focus + label,
input:not(:placeholder-shown) + label {
color: #111;
transform: translate(0, -2.75rem);
}
}
Another possibility for this cool form style is to only move the label
when a user types something. For this, you can simply remove the input:focus + label
selector. Here is the result.
I hope you found this useful! Let me know in the comments.
Top comments (3)
Real hack without js. Thanks.
Very cool...animus..Peace && Love
it's possible to use
position:absolute;
to prevent the label from taking up space on the page.