Patterns

Forms

These conventions are intended to provide guidance for both layout and proper usage of various form elements.

Designing an effective form requires consideration for its information hierarchy, sequence of form elements, clarity of labels, affordance, feedback, and accessibility.

Form layout

Form layouts organize input fields for our users to enter data and configure options. A form layout should be easy to scan, understand and complete.

Columns

Typically, forms should be one column. Multiple columns can be disruptive to a user’s vertical momentum. However, related fields are sometimes represented as a group on a single row when a mental model suggests they be treated as a singular concept. For example, city, state, and zip might be considered an "address".

Use to handle most aspects of a form's layout.

Sections

Form fields that are related should be grouped together and labeled.

  • Use to make sure your grouping is formatted and labeled properly.
  • If necessary, provide a concise description of what's represented in each section.
  • Radio buttons and checkboxes should be grouped using a as well.
  • If does not work for your use case you can use <fieldset> and <legend>, but note that you'll probably have to override the default styles.

Labeling form fields

All form fields should be labeled to help users fill out the form and take the appropriate action.

  • It's prefered that all form fields have a visible label.
  • Use , which will add the label association for you. Or use , making sure to associate the label with the form field using .
  • If there isn't enough space for a visual label you can use an aria-label on the field instead.

If your labels are properly associated, clicking on the label for a form element should focus the input field.

Optional vs. required fields

Fields in a form should be required by default. If all fields in a form are required, it should be stated at the top of the form e.g. “All fields required”.

If a form has a mix of required and optional fields, mark the required fields with an asterisk (*) and include a legend at the top of the form e.g. “* = Required” or "* Indicates required information”. Be mindful when requesting optional information. Added fields increase cognitive load and the perceived effort required to complete a task.

Input fields

The length of the text field affords the length of the answer expected. Employ this for text fields that have a defined character count like phone numbers, zip codes, etc.

Helper text

Is used to provide additional guidance with a form field. Helper text is added via the prop.

Helper text should be:

  • Meaningful and concise
  • Sentence case

Placeholder text

By default, inputs should not have placeholder text. This helps reduce visual noise and confusion on whether an input has already been filled. Placeholder text is not accessible to all users and should not be required to understand an input field. Ideally, use helper text instead, especially when describing specific, uncommon examples or instructions e.g. API keys or URL formatting.

If you do use placeholder text, it should:

  • Describe specific, uncommon examples or instructions.
  • Be short and concise.
  • Be written in plain language.
  • Disappear when a user enters data into the input field.

Checkboxes & radio buttons

Always align checkboxes and radio buttons vertically and group them with a .

Form submission

Most forms should have a submit button. Use primary or secondary for a main call to action and default for a secondary action. Always use a descriptive call to action.

Asynchronous inputs should mostly be avoided. Use your best judgment when deciding whether or not your specific needs warrant one. Be sure to provide users with clear feedback about the state of the input and submission.

Validation and errors

Validation should occur on submission of the form.

Real-time validation can be messy and distracting for the user. Only use real-time validation in scenarios where errors can be easily prevented. For example, a character counter for an input with character limit.

A form error should be associated with the input that's causing the error. The component does this for you, but if you have to roll your own, make sure to use aria-describedby on the input to point to the id of the error.

Error messages should:

  • Be clear and explain what is incorrect and how to fix it.
  • Be short and concise, single sentence, and sentence case.
  • Be written in plain language.

Do’s and Don’ts

do

Group related information logically. Use to create sections.

don't

Use text as an alternative to a label.

do

Use the prop that is built in to the component to manage labels.

don't

Use in place of built in .

do

Rely on the built in validation in the component rather than creating custom styling.

don't

Validate in real-time unless it helps users in the case of creating a password, username, or message with a character count.

do
Tailor the length of form fields based on the content.

Resources and Inspiration