Let's create a floating label input with HTML and CSS only
Tags: webdev, tutorial, css, html
Published: 2019-11-06 06:36:50

---
title: Let's create a floating label input with HTML and CSS only
published: true
description: Let's create a floating label input with HTML and CSS only. Javascript is used to achieve this result in most cases, but it can also be done without it.
tags: webdev, tutorial, css, html
cover_image: https://thepracticaldev.s3.amazonaws.com/i/11jxfm68lkpqhmsr6mas.JPG
---

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](http://mds.is/float-label-pattern/) in 2013 and it has become a widespread pattern since then, even becoming a standard element in Google's Material Design.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/xvp5hv3imi3t5em6e4yi.png)
<figcaption>Floating label input from Google Material UI docs</figcaption>

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
* Accessible

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.
* Browser support - depending on the implementation, you either need to use Javascript (performance concerns, JS dependency, etc.) or more modern CSS (doesn't support Edge and IE browsers).
* Label becomes smaller on input focus and if it has value - it can be harder to read.

## Requirements and specification

For this example, we will implement this input without the use of Javascript and use modern CSS syntax. That means that Edge and Internet Explorer browsers won't fully support the visual features and transitions, but it will remain usable.

Our implementation is going to follow the design that's been [optimized for high quality UX and is based on user research](https://medium.com/google-design/the-evolution-of-material-designs-text-fields-603688b3fe03).

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.

## Accessible markup

```html
  <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.

{%link https://dev.to/adrianbdesigns/accessibility-hiding-content-30of %}

## Styling

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-shown` CSS selector and `placeholder` HTML 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 `:focus` CSS 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 `translate3d` and `scale3d` to add support for **hardware acceleration** to our animations. Most of the other CSS-only solutions use absolute position CSS attributes like `top` and `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.

{%link https://dev.to/prototyp/improving-css-performance-and-file-size-an-in-depth-guide-4mb5 %}

Some of the other CSS-only solutions make use of `required` HTML attribute and `:valid` or `: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

{%codepen https://codepen.io/AdrianBece/pen/KKKZQOY %}

## Edge and IE fallback

As mentioned before, we have used modern CSS syntax instead of JavaScript and we got much cleaner and performant markup, but we've also decreased browser support since Edge and Internet Explorer don't support the `:placeholder-shown` selector.

Luckily, our example is **still usable on those browsers**. We only don't show animations and labels are always displayed in their focused state. We can also use **Browser-specific selectors (hacky)** or make use of **Modernizr (Javascript)** (if already included in the project) to provide a better fallback for those browsers.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/o2r3zkjb2dww304343pm.JPG)
<figcaption>Our example in Microsoft Edge & IE 11</figcaption>

<hr />

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.

<a href="https://www.buymeacoffee.com/ubnZ8GgDJ" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-red.png" alt="Buy Me A Coffee" style="height: 51px !important;width: 217px !important;" ></a>

Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.