One of those nifty things Google did with the Material Design guidelines is include floating labels. Don't know what a floating label is? Check it out:
Being the ever-curious sort that I am, I wondered if this could be accomplished sans JavaScript. Turn out, it can, but only for required fields.
Here's the demo:
https://codepen.io/peiche/pen/xOVpPo
(Note: as far as I know, CodePen embeds aren't yet supported on dev.to. Please correct me if I'm wrong!)
To make this work, the markup has to be structured in a very specific way: the input has to be in front of the label. (Don't forget the for
attribute on the label!)
In this example, I've given the label a class, form-control-placeholder
, and made it absolutely positioned. The container, which holds the label and input, is set to be relatively positioned, so the label can act as an overlay to the input itself, appearing as the placeholder.
.form-group {
position: relative;
margin-bottom: 1.5rem;
}
.form-control-placeholder {
position: absolute;
top: 0;
padding: 7px 0 0 13px;
transition: all 200ms;
opacity: 0.5;
}
Then we add a style to move the label above the input when it (the input) has focus. This is why we put the input before the label; CSS only works in one direction (although changing this is on many a developer's wish list for CSS 4.0, including yours truly).
.form-control:focus + .form-control-placeholder {
font-size: 75%;
transform: translate3d(0, -100%, 0);
opacity: 1;
}
Unfortunately, this is not enough. As soon as the input loses focus, the label will shoop right down again, covering up the input, not caring at all about whether or not you just entered some text there. (Yes, in my head the label makes a "shoop" sound whenever it moves.)
There is no way to determine via CSS alone whether an input has something entered. The closest we can get is the :valid
selector, which is only fulfilled on inputs that have the required
parameter.
So, we update the CSS to include :valid
:
.form-control:focus + .form-control-placeholder,
.form-control:valid + .form-control-placeholder {
font-size: 75%;
transform: translate3d(0, -100%, 0);
opacity: 1;
}
And now we have a working example of CSS-only floating labels. Unfortunately, there's no way to get around that required
, um, requirement, without resorting to JavaScript.
This post was originally published on eichefam.net.
Top comments (9)
You're correct about the lack of CodePen tag, will try to get it up soon.
I believe there is a way to get around the
required
requirement.Use
.form-control:not(:placeholder-shown) + .form-control-placeholder
.On another note,
:pseudo + .sibling
doesn't work in IE or Edge.Since writing this, I have learned a lot about the
:placeholder-shown
pseudo-class. Thanks!...and placeholder-shown is experimental and does not work with IE or Edge.
developer.mozilla.org/en-US/docs/W...
It gets worse.
IE has
:-ms-input-placeholder
as a selector for:placeholder-shown
and Edge does not.Whereas Edge has
::-ms-input-placeholder
as an element for::placeholder
and IE does not.Shoop ๐๐ป
A small drawback is that you now can't use the form constraints API anymore to validate in the front-end.
Well done dude! This is perfect for what I was after!
This doesn't work for me.