October 29, 2024
The 'Float label pattern' in pure CSS
The 'Float label pattern' has been around for quite a while - at least for 10 years
When Googling this post from Matt D. Smith in 2013 shows up: http://mds.is/float-label-pattern/. If you're not familiar with the concept, I'll recommend you read the post by Matt as I'm not going to describe it in depth here.
EDIT: The original post from Matt. D Smith doesn't exist anymore, but there's a Dribble Shot from Matt here: https://dribbble.com/shots/1254439--GIF-Mobile-Form-Interaction. I've also found a very short article from Brad Frost giving credit to Matt: https://bradfrost.com/blog/link/how-the-float-label-pattern-started/. Brad talks about the pattern here: https://bradfrost.com/blog/post/float-label-pattern/
Back in 2013 it required more than just CSS to get it working properly, but with the :placeholder-shown CSS pseudo-selector it's now a pretty simple task to get it working in all browsers.
Let's have a look at how it works.
input:placeholder-shown
{
// styles for input when the placeholder is shown
}
input:not(:placeholder-shown)
{
// styles for input when the placeholder is not shown
}
When working with the float label pattern we don't necessarily want to change styling of the input itself, but the label for the input.
Usually you'd want to place the label after the input field in the HTML and use the + selector to target the label. But let's do it in another, and more flexible, way. You've been reading a long in the other posts right? đ Then you'll know that we have a parent selector in the :has CSS pseudo-selector. Let's use this instead - it enables us to completely ignore in which order the input field and label is actually placed in the HTML.
Our HTML could look somethings like this:
<form class="form">
<div class="form__input-wrap">
<label for="name" class="form__label">Name</label>
<input type="text" id="name" placeholder="Name" class="form__input" />
</div>
</form>
What we want to do now is:
Place the label on top of the input field when the placeholder is shown.
Move up, and scale the label a bit down, when the placeholder is not shown.
Let's have a look at how we can do this:
.form__input-wrap:not(:has(input:placeholder-shown)) .form__label {
transform: translateY(-8px) scale(0.8)
}
This way we easily target the label for the input field, when the parent (.form__input-wrap) doesn't have a child with the placeholder is shown. And when the placeholder isn't shown, it means that the user must have entered something in the field. So we move up the label and scale it a bit down.
We could change the font-size of the label, but if we want to do any animating, we'd want to do it on the transform attribute (and/or the opacity attribute). Josh Collinsworth explains why in a great post with 10 tips for better CSS transitions and animations.
I've made a Codepen with some more HTML surrounding the form fields, but in essence, I'm just doing what I've been explaining above. Here you go:
This is just a very simple example of how to implement the 'Float label pattern' on your forms. But there's a lot more to user-friendly forms than just this. You'll need to have great visual validation for the user:
Validate required fields
Validate e-mail input
Validate numeric values
Validate other fields that might have to be in a specific format using the pattern attribute
There's some different ways to do this, but the most common is to add a checkmark when the field is valid and an error-icon, of some sort, when the field is not valid. The icons could be placed after the label - and the label text color could be changed to green and red for respectively valid and invalid fields.
For form validation in pure CSS you might want to take a look at the :valid, :invalid, :user-valid and :user-invalid pseudo-selectors. For JavaScript validation I recommend you take a look at the checkValidity() and reportValidity() methods.
As always - if you've got other examples and maybe better ways to implement the 'Float label pattern', let me know. I'll update the post and credit you. You can send me an email at [email protected].