Pure CSS, Accessible, floated, form labels

I was on the lookout for an accessible, pure CSS, floated form label. Lots of different solutions were available, but none fully suited my needs.

Requirements were:

  • No JavaScript
  • It had to be accessible
  • It had to use appropriate html attributes, or failing that, attributes that would not affect its use, or accessibility
  • The label appears if the input receives focus – even when the input has data

After searching for quite a while I found “Javascript-full Float Label Pattern by Jordan Little” but it used Javascript to add/remove classes. I was able to remove the Javascript and edit the CSS to the point where it met most of my requirements, but I hit a wall when an input which had data, lost focus – the label would return to its position and cover the value. So I tried a different approach.

I gave each input a placeholder (In reality we don’t need a placeholder, as the floating label will be filling that role.

However the reason it was added is that, an input shows a placeholder when there is data, and it doesn’t when there is no data, using the :placeholder-shown pseudo-class the input can potentially have two different states. Using adjacent selectors I could then pass those states to the label, and style it accordingly.The finished form acts like this:

The HTML is very straightforward

<div class="labfloat">
<input type="text" id="name" placeholder="name" />
<label for="name">Name</label>
<div class="labfloat">
<input type="email" placeholder="email" id="email" required />
<label for="email">Email</label>


The only noteworthy thing is, I’ve added a div.labfloat around each form field and label, this will be used to position elements within it:

.labfloat {

Then we hide the real placeholder text – it’s not needed, as we will be using the <label> in its place:

::placeholder {

In order for the label to be correctly positioned over the input when it is in focus we reduce the bottom padding of the input:

input {
padding:1.4rem 1rem .6rem 1rem;
border:1px solid #aaa;
font: 1.3rem "Open Sans", sans-serif;
transition: all .25s ease-in-out;

We set the default positioning of the label, this visually positions the label inside and over the input, giving it the appearance and positioning of placeholder text:

input + label {
transition: all .25s ease-in-out;
font: 1.3rem "Open Sans", sans-serif;

When the input receives focus we reposition the label, closer to the top of the input and reduce its size:

input:focus + label {
font-size: 1rem ;

When the placeholder is not shown – eg. when the input has data, change the input padding to vertically center the data:

input:not(:placeholder-shown) {

Also, when the placeholder is not shown – we need to hide the label:

input:not(:placeholder-shown) + label {

If a form field with data receives focus, we want to make the label visible again:

input:focus:not(:placeholder-shown) + label {

If the user returns to edit the input data change the padding again, to accommodate the now-visible label and the data:

input:focus:not(:placeholder-shown) {
padding:1.4rem 1rem .6rem 1rem;

This is it below, I’ve no doubt it can be improved, and I’ve probably made a few errors, please let me know below if I have. I’ve only tested it on modern browsers, as it’s meant for mobile.

See the Pen Flat minion by Cormac Maher (Cormac Maher) on CodePen

Leave a Reply

Your email address will not be published. Required fields are marked *