Let's create a floating label input with HTML and CSS only
Floating label input is an element that visually combines an input label and the input itself into a single element. Label switches from placeholder mode to label when input is focused or has content in it. This concept has been first introduced by Matt D. Smith in 2013 and it has become a widespread pattern since then, even becoming a standard element in Google's Material Design.
Floating label input from Google Material UI docs
There are several reasons why this pattern in being used even today:
- It saves space
- Looks clean and it makes scanning the form easier
- Looks amazing with smooth transitions
But there are also a few things that both developer and designer need to be aware of:
- Cannot use both label and placeholder - label also takes place of a placeholder.
- Label becomes smaller on input focus and if it has value - it can be harder to read.
Requirements and specification
Our implementation is going to follow the design that's been optimized for high quality UX and is based on user research.
Transitions (animations) need to be smooth and make use of hardware acceleration where possible.
We also want to make the input accessible and preserve the native tab navigation.
<div class="floating"> <input id="inputId" class="floating__input" name="input name" placeholder="Placeholder" /> <label for="inputId" class="floating__label" data-content="Placeholder"> <span class="hidden--visually">Placeholder</span> </label> </div>
We are going to use a wrapper element
<div class="floating"> just to wrap the input-label pairs into a single container and to handle spacing between the inputs. The wrapper element is not required, but it makes styling the group easier.
We are also using accessible hiding of elements with
<span class="hidden--visually">. I've covered this method of hiding elements in one of my previous articles .
The code required for styling this element is around 80-95 lines of code, so I decided to focus on explaining only specific, more complex, parts. Entire HTML and CSS code can be seen in the Codepen example below.
Styling implementation details:
- We are using
:placeholder-shownCSS selector and
placeholderHTML attribute to let the browser do the logic of detecting when the label should be resized to a smaller size or displayed at full size
- We are using CSS variables to easily change the color scheme
- We are using
:focusCSS selector to allow keyboard tab interaction along with the regular click(or touch) interaction
CSS transitions and animations need to be smooth, so we are going to use
scale3d to add support for hardware acceleration to our animations. Most of the other CSS-only solutions use absolute position CSS attributes like
left for transitions that need to be avoided due to poor performance. I've covered this topic more in-depth in one of my previous articles .
Some of the other CSS-only solutions make use of
required HTML attribute and
:invalid selectors to determine when the label needs to be transformed, which is hacky and semantically incorrect. Also, it makes the implementation impossible for non-required inputs.
In our implementation, label transformation logic is shared with placeholder display logic so it makes the code more semantically correct and flexible.
Example & source code
Edge and IE fallback
Our example in Microsoft Edge & IE 11
These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.
Thank you for taking the time to read this post. If you've found this useful, please give it some likes, share and comment.