Forms
A form is a group of related input controls that allows users to provide data or configure options. Forms can be simple or complex, and may be presented as dedicated pages, side panels, or dialogs depending on the use case and the situation.
Table of Contents
Edit this section, Opens in new windowOverview
When to use
Forms are incredibly common in user interfaces and their design and usage continues to evolve as input methods get smarter and more and more people use mobile and tablet devices. You might design a form for a user to:
- Sign up for / log into an account
- Register for a service
- Reconfigure settings, (e.g. enabling notifications)
- Take a survey
- Purchase a product
- Provide feedback
Respect the user
Forms are meant to gather information and guide people with as little fuss as possible. To allow users to scan and complete the form quickly, forms should:
- Respect the user’s GDPR and other privacy regulations by only asking for information that is absolutely necessary.
- Group related tasks under section titles to provide more context and make the interface easier to scan.
- Follow a logical, predictable order—e.g first name first, last name second.
- Allow users to stay with a single interaction method for as long as possible (i.e. do not make users shift from keyboard to mouse numerous times in a single form).
- When designing be mindful of password managers and browser capabilities that populate data for users.
- Progressively disclose additional inputs only as they become relevant
Style
Layout
TBD
Accessibility
When constructing a form, first refer to the specific accessibility guidance for each component used. Every text input
should have a descriptive and visible label, along with hard coded instructions for input format. A form must be wrapped
in a <form>
element.
Requirements for your form should be announced and declared before the user enters the form.
The most significant challenge facing visually impaired users is form ordering. Your form should be tab-navigable, and required fields should be clearly labeled as such.
Validation messages should be included to advise the user of data that is input incorrectly or a required field that is missing information.
Helper text (label
) should be used to provide instructions to help users understand how to complete the form fields as
well as indicate any required and optional input, data formats, and other relevant information.
See the WCAG website for in-depth accessibility guidance for each form element.
Validation
We want to make filling out web forms as easy as possible. So why do we insist on validating our forms? There are three main reasons:
- We want to get the right data, in the right format. Our applications won't work properly if our users' data is stored in the wrong format, is incorrect, or is omitted altogether.
- We want to protect our users' data. Forcing our users to enter secure passwords makes it easier to protect their account information.
- We want to protect ourselves. There are many ways that malicious users can misuse unprotected forms to damage the application.
Effective and immediate error messaging can help the user to understand the problem and how to fix it. First, inform the user what has happened, then provide guidance on next steps or possible resolutions. Always present error states on the form, and use inline errors whenever possible.
Client-side validation
We recommend validating the user’s data before form submission. This type of real-time, inline validation (a.k.a. client-side validation) should happen as soon as the field loses focus. This will help to easily identify the elements that need to be corrected.
The validation label below the field should be as informative as possible when describing the issue with the user’s data. For example, if password limitations require 16 characters, but the user inputs a password with only six characters, the text should read something like, "Password must be at least 16 characters."
Example
This example uses the Constraint validation API.
The html:
<form novalidate action="" class="if">
<div class="if input-wrapper">
<input
data-size="larger"
required
placeholder="Enter your first name"
name="first_name"
id="first_name"
type="text"
minlength="2"
class="if input-field"
/>
<label class="if" for="first_name" aria-describedby="first_name_help-1 first_name_error-1"
>First name*</label
>
<span class="if input-error" id="first_name_error-1" aria-live="polite"
>A validation error</span
>
<span class="if input-help" id="first_name_help-1">A helpful text</span>
</div>
<div class="if input-wrapper">
<button type="submit" id="submit" class="if primary button">Submit</button>
</div>
</form>
This simple form uses the novalidate
attribute to turn off the browser's automatic validation; this lets our script take control over validation. However, this doesn't disable support for the constraint validation API nor the application of CSS pseudo-classes like :valid
, etc. That means that even though the browser doesn't automatically check the validity of the form before sending its data, you can still do it yourself and style the form accordingly.
Our input to validate is an <input type="text">
, which is required
, and has a minlength
of 2 characters. Let's
check these using our own code, and show a custom error message for each one.
Now, let's look at the JavaScript:
const forms = document.querySelectorAll('form');
const isAllElementsValid = (els) => els.filter((el) => !el.validity.valid).length === 0;
forms.forEach((form) => {
const formElements = Array.prototype.filter.call(
form.elements,
(el) => el.nodeName !== 'BUTTON'
);
formElements.forEach((el) => {
el.addEventListener('blur', (e) => {
if (el.validity.valid) {
// In case there is an error message visible, if the field
// is valid, we remove the error message.
el.parentElement.querySelector('span.if.input-error').innerHTML = '';
el.classList.remove('is-invalid');
el.removeAttribute('aria-invalid');
} else {
// If there is still an error, show the correct error
showError(el);
}
});
});
form.addEventListener('submit', (e) => {
// if all fields are valid, we let the form submit
if (!isAllElementsValid(formElements)) {
// If it isn't, we display an appropriate error message
showErrors(formElements);
// Then we prevent the form from being sent by canceling the event
event.preventDefault();
} else {
alert('valid');
}
});
});
const showErrors = (els) => {
els.forEach((el) => {
showError(el);
});
};
Show error:
function showError(el) {
const errorEl = el.parentElement.querySelector('span.if.input-error');
if (el.validity.valueMissing && el.required) {
// If the field is empty
// display the following error message.
// You can use the given el to extract label, name etc. to
// provide more meaningful error messages
errorEl.textContent = 'You need to enter something.';
el.classList.add('is-invalid');
el.setAttribute('aria-invalid', true);
} else if (el.validity.typeMismatch) {
// If the field doesn't contain the correct type
// display the following error message.
// You can use the given el to extract label, name etc. to
// provide more meaningful error messages
errorEl.textContent = 'Entered value needs to be an of correct type.';
el.classList.add('is-invalid');
el.setAttribute('aria-invalid', true);
} else if (el.validity.badInput) {
// If the field doesn't contain input the browser can't convert,
// i.e. strings in a number field, we
// display the following error message.
// You can use the given el to extract label, name etc. to
// provide more meaningful error messages
errorEl.textContent = `Bad input, please enter a ${el.getAttribute('type')}.`;
el.classList.add('is-invalid');
el.setAttribute('aria-invalid', true);
} else if (el.validity.tooShort) {
// If the data is too short
// display the following error message.
// You can use the given el to extract label, name etc. to
// provide more meaningful error messages
errorEl.textContent = `Value should be at least ${el.minLength} characters; you entered ${el.value.length}.`;
el.classList.add('is-invalid');
el.setAttribute('aria-invalid', true);
}
}
The comments explain things pretty well, but briefly:
- Every time we change the value of the input, we check to see if it contains valid data. If it has then we remove any
error message being shown. If the data is not valid, we run
showError()
to show the appropriate error. - Every time we try to submit the form, we again check to see if the data is valid. If so, we let the form submit. If
not, we run
showError()
to show the appropriate error, and stop the form submitting withpreventDefault()
. - The
showError()
function uses various properties of the input's validity object to determine what the error is, and then displays an error message as appropriate.
This code can also be seen and experienced on CodePen.
Server-side validation
TBD
Anatomy
Forms are comprised of some or all of the following elements.
- Form headline
- Form description
- Input field
- Label
- Placeholder text
- An optional field
- Help tooltip
- Error message
- Required field
- Help text
- Button
Form headline
Form description
Input field
Please see the Input Fields documentation for more information about input fields.
Label
Effective form labeling helps users understand what information to enter into a form input. Using a placeholder text as a label is often applied as a space-saving method. However, this is not recommended because it hides context and presents accessibility issues.
Please see the Input Labels documentation for more information about input labels.
Text input
Data input
Selection controls
Radio buttons
Please see the Radio Button documentation for more information about Radio Buttons.
Checkboxes
Please see the Checkbox documentation for more information about checkboxes.
Toggle
Please see the Toggle documentation for more information about toggles.
Dropdown Select
Please see the Dropdown Select documentation for more information about dropdown selects.
Numeric Stepper
Please see the Numeric Stepper documentation for more information about numeric steppers.
Autocomplete
File upload
Placeholder text
Placeholder text provides hints or examples of what to enter (e.g. YYYY-MM-DD). Since placeholder text disappears once the user begins to input data, it should not contain crucial information. When the requested input may be unfamiliar to the user or formatting is in question, use placeholder text.
Do:
- Keep hints as short as possible and never overrun the input field.
- Properly anonymize examples rather than using real values.
Don't:
- Use placeholder text to communicate complex and lengthy requirements like password requirements. Instead, use a help tooltip.
- Provide placeholder text when it isn't necessary.
- Ever use placeholder text as a replacement for field labels.
Help tooltip
Tooltips can be very useful for providing additional explanation to users that may be unfamiliar with a particular form field. They can also offer rationale for what may seem like an unusual request. However, research suggests that users should not have to dig around for a tooltip to access information that's essential for the completion of their task.
The help tooltip button is triggering a popover. Please see the Help Tooltip documentation for more information about Help Tooltip.
Do:
- Use tooltips for explanatory or added information.
- Tooltips are microcontent; keep them concise.
Don't:
- Tooltips are not catchalls for content that doesn't fit elsewhere; they must be used intentionally and very sparingly.
- Never house essential information in a tooltip.
Error message
An error message is displayed when the form or form element is invalid. The message should be short and simple, so that the user can act on it.
If you are in need for a larger error text, you can use a red popover. NOTE: Use sparingly! There should not be many cases requiring long validation error messages.
For text fields that validate their content (such as passwords), replace helper text with error text when applicable. Swapping helper text with error text helps prevent new lines of text from being introduced into a layout, thus bumping content to fit it.
- If only one error is possible, error text describes how to avoid the error
- If multiple errors are possible, error text describes how to avoid the most likely error
Help text
Help text appears below the input label and assists the user to provide the right information. Help text is always available, even when the field is focused, that's why it's the correct choice for need-to-know information. For context or background information that is "nice to have", use placeholder text or a tooltip.
Do:
- Think of helper text as crucial information that is secondary to the input label.
- Keep helper text as short and specific as possible.
- Only use helper text when truly necessary to avoid overloading the user.
Don't:
- Never use helper text in place of field labels.
- Helper text should not run longer than the input area.
Button
Allows users to submit or exit a form.
Use a primary button for the main action, a secondary button for secondary actions like "Cancel" or "Discard".
Please see the button documentation for more information about buttons.