When it comes to creating forms on webpages, accessibility and design have to go hand in hand. Ideally, every input field should have an associated label and a placeholder, if needed. However, from a design perspective, this can cause a form to look rather text-heavy.
Labels-as-placeholders, sometimes known as floating labels, are a popular design choice for creating minimalist and accessible forms. This method is also commonly used in popular design systems such as Bootstrap and Material Design (shown below):
In this tutorial, we’ll recreate the floating label used in Material Design text fields using CSS and vanilla JavaScript.
Material Design Floating Label
Here’s what the final result looks like:
Begin With Form HTML Markup
First, we create the markup for our Material Design form including a label and an input text field.
<div class="input-container"> <input type="text" id="name" required/> <label for="name">First Name</label> </div> </form>
It's important to associate labels to their related input fields by using the for
attribute and the id
of the input. This is used by screen readers to communicate the details of the form.
Using the DevTools Accessibility pane, we can see how labels and inputs are linked in the form markup above:
Material Design Form CSS
The most important styling for a floating label is to make the label absolutely positioned inside a relative parent element. We want to be able to move our label around the input container without it disrupting the flow of elements.
.input-container { position: relative; height: 56px; } label { display: block; position: absolute; top: 50%; transform: translateY(-50%); }
Float Label on Focus
We also want to float the label whenever the user clicks the input. We can do this using the :focus
and + (plus)
selector. When the input is focused on, we change the position, size and color of the label.
input:focus + label { transform: translateY(-100%) scale(0.75); color: #6200ee; }
Note: This works because the label is the next element immediately after the input field. The plus selector targets the next immediate element so it won't work if the label is placed before the input or another element is placed in between the two.
Float Label with User Input
Another feature of the floating label is that it remains floated if the input has a value, even if the user is no longer focusing on the input.
We can achieve this by using the CSS :valid
selector and the required
attribute in the HTML markup
We use the valid selector for required inputs to detect if the input has a value.
input:focus + label, input:valid + label { transform: translateY(-100%) scale(0.75); }
With this, the label remains floated when the input is focused or has a value.
Unfortunately, there are some drawbacks to using the valid selector. For example, if the valid selector is used on an email input, the input is considered invalid if the value is not in email format.
We can solve this with a little JavaScript.
Add JavaScript Event Listener
We use JavaScript to detect if the input has a value whenever the user navigates away from it.
const inputs = document.querySelectorAll("input"); inputs.forEach((input) => { input.addEventListener("blur", (event) => { if (event.target.value) { input.classList.add("is-valid"); } else { input.classList.remove("is-valid"); } }); });
Whenever the input loses focus, we check if it contains a value. If it does, we add the is-valid
class, if not we remove the valid class. We can update our CSS styling to float the label with the is-valid
class.
input:focus + label, input.is-valid + label { transform: translateY(-100%) scale(0.75); }
With this we’ve implemented the floating label design!
Here’s the complete CSS to recreate the Material Design form look.
.form-container { height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; background-color: #fafafa; } form { padding: 3rem; display: flex; flex-direction: column; gap: 2rem; width: 95%; max-width: 300px; background-color: white; border: 1px solid rgba(0, 0, 0, 0.12); border-radius: 0.5rem; box-shadow: 0 0 8px 0 rgb(0 0 0 / 8%), 0 0 15px 0 rgb(0 0 0 / 2%), 0 0 20px 4px rgb(0 0 0 / 6%); } .input-container { background-color: #f5f5f5; position: relative; border-radius: 4px 4px 0 0; height: 56px; transition: background-color 500ms; } .input-container:hover { background-color: #ececec; } .input-container:focus-within { background-color: #dcdcdc; } label { display: block; position: absolute; top: 50%; transform: translateY(-50%); left: 16px; color: rgba(0, 0, 0, 0.5); transform-origin: left top; user-select: none; transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1),color 150ms cubic-bezier(0.4, 0, 0.2, 1), top 500ms; } input { width: 100%; height: 100%; box-sizing: border-box; background: transparent; caret-color: #6200ee; border: 1px solid transparent; border-bottom-color: rgba(0, 0, 0, 0.42); color: rgba(0, 0, 0, 0.87); transition: border 500ms; padding: 20px 16px 6px; font-size: 1rem; } input:focus { outline: none; border-bottom-width: 2px; border-bottom-color: #6200ee; } input:focus + label { color: #6200ee; } input:focus + label, input.is-valid + label { transform: translateY(-100%) scale(0.75); }
Your Material Design Floating Labels Are Complete!
As with most design patterns, floating labels have triggered their fair share of debates. So long as you make your forms accessible and easy to use, you can use any design pattern you like. Hopefully, this tutorial serves as a useful guide should you choose to use floating labels.
More Form Design Tutorials
Learn more about form design patterns, floating labels, Material Design forms, and form accessibility here on Tuts+:
-
CSSBetter Focus Styles with CSS Pseudo-Class :focus-visible
-
ValidationHTML5 Form Validation With the “pattern” Attribute
-
Form DesignQuick Tip: Add a Formspree Form to Your Static Sites
-
FormsHow to Customize Contact Form 7 for WordPress: Floating Labels
-
AccessibilityHow to Make Custom Accessible Checkboxes and Radio Buttons
-
Material Design LiteLearning Material Design Lite: Text Fields
No comments:
Post a Comment