Accessible floating labels

Comment icon Small gray icon for comments Comments

This post has been updated to reflect a CSS-only approach without the use of the placeholder attribute on input elements.

There’s been plenty of discussion in recent months regarding accessibility as it relates to the use of labels, which I think is great. Web designers and developers should treat accessibility as a fundamental part of development and not an afterthought.

Still, I see plenty of implementations where labels are ignored for more eye-catching solutions, which in turn creates accessibility problems. Interestingly enough, there are plenty of existing, design-friendly patterns using labels. One that’s been around for a few years now is floating labels:

And it’s pretty easy to implement with a small amount of CSS and jQuery.

The markup

Let’s assume we need to build a registration form like the one above. We’ll start with the first input and label:

<div class="field">
  <input type="text" id="firstName">
  <label for="firstName">First Name</label>
</div>

Here we’re using placeholder inside the input to specify a short hint to aid the user, but not as an alternative to a label.

The CSS

The input and label are wrapped inside a container class so the label’s interaction will be relatively positioned to the input:

.field {
  position: relative;
}

The label selector will be defined with this basic ruleset:

label {
  left: .5em;
  opacity: 1;
  position: absolute;
  top: .25em;
  transition: all 0.1s linear;
}

The label’s initial position will be “inside” the input element (it’s actually just resting on top of it). Now we’ll add a class for this selector that will be dynamically added on user input: We want to transition the label’s position when the input has focus so it moves above the input:

input:focus + label,
input + label.show {
  color: #2ea8c5;
  font-size: 1.15em;
  left: .75em;
  opacity: 1;
  top: -1em;
}

The .show class will be used by our jQuery code, so let’s get started on that.

The jQuery

First, let’s create a function and add a variable for the .show class:

$(function () {
  let showClass = 'show';
});

Next, we’ll add an inner function that checks if <input> is empty:

$(function () {
  let showClass = 'show';
  
  $('input').on('checkval', function () {
    let label = $(this).next('label');
    if(this.value !== '') {
      label.addClass(showClass);
    } else {
      label.removeClass(showClass);
    }
  })
});

If the input has a value then the .show class will be added to the label to keep it positioned above the input.

Lastly, we’ll include an event listener for when the user enters a character, which checks the value of <input>:

$(function () {
  let showClass = 'show';
  
  $('input').on('checkval', function () {
    let label = $(this).next('label');
    if(this.value !== '') {
      label.addClass(showClass);
    } else {
      label.removeClass(showClass);
    }
  }).on('keyup', function () {
    $(this).trigger('checkval');
  });
});

There you have it.

See the Pen Accessible Floating Labels by Matt Smith (@AllThingsSmitty) on CodePen.

Accessibility FTW!

The point here isn’t to ignore accessibility in favor of design. The challenge is to craft an experience that’s not only functional for some users, but to fully engage all users by making accessibility an integral part of development!