Placeholder text in forms might be thought of as a user experience add-on, but its real-world use is problematic. While there are several issues with placeholder text, a few points to note are:

  • The text might not be translated by auto-conversion tools such as Google Translate.
  • The default color of placeholder text might be too low in contrast for legibility.
  • The text disappears when users start typing, and then people can forget the input’s purpose, especially if the label is visually hidden.

There are options to give forms a sense of style without relying on placeholder text.

We suggest one solution — you can see the code on our CodePen — that includes positioning the label element so that it overlaps the input field. In effect, making the label look like placeholder text. Then when the input receives focus, animate the label element out of the user’s way. Let’s dive into one approach using CSS positioning and transitions:

Note: A previous animated labels solution that we presented is still valid, however the form labels were placed after their respective input fields. While that solution is still valid, we wanted to update the example with a typical design pattern.

Building Out the Form

First step is to set up the form inputs and labels. This pattern allows us to easily move the label text with CSS rules (which we will get to later on).

<div class="field">
  <label for="username">Username <span aria-hidden="true">*</span></label>
  <input type="text" name="username" id="username" required>
</div>
<div class="field">
  <label for="password">Password <span aria-hidden="true">*</span></label>
  <input type="password" name="password" id="password" required>
</div>

Note: We are hiding the asterisk (*) from screen readers because it is only announced as “star,” which may not be a clear indication for users that the field is, indeed, required.

Placing the Form Labels

Move the labels to overlap the input fields.


form input,
form label {
  position: relative;
  display: inline-block;
  width: 100%;
}
form label {
  display: inline-block;
  margin: 0 auto;
  padding: 0 0 5px 0;
  top: 36px; /* moving label down */
}

To avoid obscuring the input fields from interaction, stack the labels behind the input fields by setting the z-index value on the labels lower than that of the input fields:


form label {
  display: inline-block;
  margin: 0 auto;
  padding: 0 0 5px 0;
  top: 36px;
  z-index: 1; /* placing label behind input */
}
form input[type="text"],
form input[type="password"] {
  font-size: 1.25em;
  padding: 0 0 5px 0;
  margin-bottom: 0.5em;
  z-index: 10;
  border: none;
  border-bottom: 2px solid black;
}

The input fields are now blocking the labels from the user’s view. To see the labels, set the form inputs’ background to transparent:


form input[type="text"],
form input[type="password"] {
  font-size: 1.25em;
  padding: 0 0 5px 0;
  margin-bottom: 0.5em;
  z-index: 10;
  background: transparent; /* adding transparency */
  border: none;
  border-bottom: 2px solid black;
}

Moving the Form Labels

Slide the labels above the inputs on focus. At this point, the labels are visible. However, the label text stays in place when there’s user interaction.

Set in place the CSS rules that point to where we want the labels to be moved ⁠— above the input fields ⁠— and have the text reduced in size:

.filled label {
  top: 0;
  font-size: 0.8em;
}

By swapping in and out the class through jQuery, the label text moves when the user enters the input field and stays put as content is entered. In case there is nothing entered in the input field as the user moves on, the label text moves back to its original location:

$("form input").on("blur input focus", function() {
	var $field = $(this).closest(".field");
	if (this.value) {
		$field.addClass("filled");
	} else {
		$field.removeClass("filled");
	}
});


$("form input").on("focus", function() {
	var $field = $(this).closest(".field");
	if (this) {
		$field.addClass("filled");
	} else {
		$field.removeClass("filled");
	}
});

Animating the Form Labels

As the user focuses on the input field, the labels immediately move out of the way. The effect is a little jarring. To make this change a little more graceful, apply an animation with the CSS transition property:


form label {
  display: inline-block;
  margin: 0 auto;
  padding: 0 0 5px 0;
  top: -33px;
  transition: all 0.5s ease-in-out; /* adding animation */
  z-index: 1;
}

And that’s it. You just created a form element that looks good and works well, too!

See the Pen Animated Labels (with jQuery) by Knowbility (@Knowbility) on CodePen.

See the completed version at our CodePen.

Note: Animating form labels in this manner might cause a conflict with WCAG 2.3.3 (Level AAA). If you would like to meet this success criteria and still integrate this design pattern into your project, one solution would be to use a reduced motion media query.

Conclusion

Placeholder text might seem like a great feature for your users. But those gains are, at best, superficial. Labels with form inputs ensure the widest audience possible can interact with your forms. And with just a few touches of CSS, you can provide an effect similar to placeholder text — without limiting or locking out people with disabilities.