2.23.0
Forms gather information from users via Checkboxes, Inputs, Radio Buttons, Selects and Textareas. Labels sit atop these elements.
Form wrappers always enclose all form elements.
<form class="mds-form mds-form--medium-layout">
<div class="mds-form__field-group">
<label class="mds-form__label" for="input-01">
First Name
</label>
<input class="mds-form__input" type="text" id="input-01">
</div>
</form>
<form class="mds-form mds-form--medium-layout">
<mds-field-group>
<mds-label for="input-01">First Name</mds-label>
<mds-input id="input-01"></mds-input>
</mds-field-group>
</form>
<fieldset>
, <legend>
, <label>
, and <input>
within form wrappers.By default, form elements do not include any margins. To assist with the composition of many individual form elements in a complete form, MDS provides layout modifier classes which automatically apply margin-based spacing to all elements contained within a form.
Form layout modifier classes are available for all three sizes of form elements, mds-form--small-layout
, mds-form--medium-layout
, and mds-form--large-layout
. Always apply these modifier classes to the block level of a <form>
element, for example:
<form class="mds-form mds-form--large-layout">
<div class="mds-form__field-group">
<label class="mds-form__label mds-form__label--large" for="first-name">
First Name
</label>
<input class="mds-form__input mds-form__input--large" type="text" id="first-name">
</div>
<div class="mds-form__field-group">
<label class="mds-form__label mds-form__label--large" for="last-name">
Last Name
</label>
<input class="mds-form__input mds-form__input--large" type="text" id="last-name">
</div>
<div class="mds-form__field-group">
<label class="mds-form__label mds-form__label--large" for="email">
Email
</label>
<span class="mds-form__microcopy mds-form__microcopy--large" id="email-microcopy">
Please use the Email address associated with your use account.
</span>
<input class="mds-form__input mds-form__input--large" type="text" id="email" aria-describedby="email-microcopy">
</div>
</form>
<form class="mds-form mds-form--large-layout">
<mds-field-group>
<mds-label for="first-name" size="large">First Name</mds-label>
<mds-input id="first-name" size="large"></mds-input>
</mds-field-group>
<mds-field-group>
<mds-label for="last-name" size="large">Last Name</mds-label>
<mds-input id="last-name" size="large"></mds-input>
</mds-field-group>
<mds-field-group>
<mds-label for="email" size=large>Email</mds-label>
<mds-microcopy id="email-microcopy" size="large">Please use the Email address associated with your use account.</mds-microcopy>
<mds-input aria-describedby="email-microcopy" id="email" size="large"></mds-input>
</mds-field-group>
</form>
Field groups always wrap related elements.
<form class="mds-form mds-form--medium-layout">
<div class="mds-form__field-group mds-form__field-group--error">
<label class="mds-form__label" for="input-01">
Label Text
</label>
<span class="mds-form__microcopy" id="input-01-microcopy">
Microcopy Text
</span>
<input class="mds-form__input" type="text" id="input-01" aria-describedby="input-01-microcopy input-01-error">
<span class="mds-form__field-error" id="input-01-error" role="alert">
<span class="mds-form__field-error-text">
Error Text
</span>
</span>
</div>
<div class="mds-form__field-group mds-form__field-group--horizontal">
<div class="mds-form__field-group demo-flex-grow-1">
<label class="mds-form__label" for="input-02">
Label Text
</label>
<input class="mds-form__input" type="text" id="input-02">
</div>
<div class="mds-form__field-group demo-flex-grow-1">
<label class="mds-form__label" for="input-03">
Label Text
</label>
<input class="mds-form__input" type="text" id="input-03">
</div>
<div class="mds-form__field-group demo-flex-grow-1">
<label class="mds-form__label" for="input-04">
Label Text
</label>
<input class="mds-form__input" type="text" id="input-04">
</div>
</div>
</form>
<form class="mds-form mds-form--medium-layout">
<mds-field-group error>
<mds-label for="input-01">Label Text</mds-label>
<mds-microcopy id="input-01-microcopy">Microcopy Text</mds-microcopy>
<mds-input aria-describedby="input-01-microcopy input-01-error" id="input-01"></mds-input>
<mds-field-error id="input-01-error" visible>Error Text</mds-field-error>
</mds-field-group>
<mds-field-group horizontal>
<mds-field-group class="demo-flex-grow-1">
<mds-label for="input-02">Label Text</mds-label>
<mds-input id="input-02"></mds-input>
</mds-field-group>
<mds-field-group class="demo-flex-grow-1">
<mds-label for="input-03">Label Text</mds-label>
<mds-input id="input-03"></mds-input>
</mds-field-group>
<mds-field-group class="demo-flex-grow-1">
<mds-label for="input-04">Label Text</mds-label>
<mds-input id="input-04"></mds-input>
</mds-field-group>
</mds-field-group>
</form>
id
in an element's aria-describedby
attribute. See accessibility guidelines for more information.mds-form__field-group--horizontal
modifier class or horizontal
prop. This applies margin-right
to elements contained within the child field group containers.Field sets wrap multiple deeply related elements within a form, e.g., fields for entering an address. Always include a descriptive legend using mds-form__legend
when using a field set.
<form class="mds-form mds-form--medium-layout" method="post" action="form/processor">
<fieldset class="mds-form__fieldset">
<legend class="mds-form__legend">Address</legend>
<div class="mds-form__field-group">
<label class="mds-form__label" for="full-form-address">
Address
</label>
<input class="mds-form__input" type="text" id="full-form-address">
</div>
<div class="mds-form__field-group mds-form__field-group--horizontal">
<div class="mds-form__field-group demo-flex-grow-1">
<label class="mds-form__label" for="full-form-city">
City
</label>
<input class="mds-form__input" type="text" id="full-form-city">
</div>
<div class="mds-form__field-group demo-flex-grow-1">
<label class="mds-form__label" for="full-form-state">
State
</label>
<div class="mds-form__select demo-width-100">
<select class="mds-form__select-input" id="full-form-state">
<option class="mds-form__select-option" value="default">Select your state</option>
<option class="mds-form__select-option" value="just">Just</option>
<option class="mds-form__select-option" value="kidding">Kidding</option>
</select>
<div class="mds-form__select-visual-wrap"></div>
<span class="mds-form__select-open-indicator">
<svg class="mds-icon mds-form__select-open-icon" aria-hidden="true">
<use xlink:href="#caret-down--s">
</use>
</svg>
</span>
</div>
</div>
<div class="mds-form__field-group demo-flex-grow-1">
<label class="mds-form__label" for="full-form-zip">
Zip Code
</label>
<input class="mds-form__input" type="text" id="full-form-zip">
</div>
</div>
</fieldset>
</form>
<form class="mds-form mds-form--medium-layout">
<fieldset class="mds-form__fieldset">
<legend class="mds-form__legend">Address</legend>
<mds-field-group>
<mds-label for="full-form-address">Address</mds-label>
<mds-input id="full-form-address">
<mds-input>
</mds-field-group>
<mds-field-group horizontal>
<mds-field-group class="demo-flex-grow-1">
<mds-label for="full-form-city">City</mds-label>
<mds-input id="full-form-city">
<mds-input>
</mds-field-group>
<mds-field-group class="demo-flex-grow-1">
<mds-label for="full-form-state">State</mds-label>
<mds-select additional-class="demo-width-100" id="full-form-state" placeholder="Select your state" options='[{"text": "Just", "value": "just"}, {"text": "Kidding", "value": "kidding"}]'>
</mds-select>
</mds-field-group>
<mds-field-group class="demo-flex-grow-1">
<mds-label for="full-form-zip">Zip Code</mds-label>
<mds-input id="full-form-zip">
<mds-input>
</mds-field-group>
</mds-field-group>
</fieldset>
</form>
mds-form__fieldset
and mds-form__legend
are non-visible elements that play a critical role in making forms accessible for those using assistive technologies, like screen readers. See accessibility guidelines for more information.<fieldset>
elements may be nested with another <fieldset>
, for example, if using the Radio group or Checkbox group.This example combines many form elements wrapped with a mds-form--medium-layout
modifier class to apply margin-based spacing. It uses a Required Fields Key, Labels (default and required), Inputs, Select, Textarea, and a Button.
<form class="mds-form mds-form--medium-layout" method="post" action="form/processor">
<fieldset class="mds-form__fieldset">
<legend class="mds-form__legend">Address</legend>
<span class="mds-form__required-fields-key">Required fields</span>
<div class="mds-form__field-group">
<label class="mds-form__label" for="full-form-first-name">
First Name
<abbr class="mds-form__label-required-indicator" title="This field is required." aria-label="This field is required.">*</abbr>
</label>
<input class="mds-form__input" type="text" id="full-form-first-name">
</div>
<div class="mds-form__field-group">
<label class="mds-form__label" for="full-form-last-name">
Last Name
<abbr class="mds-form__label-required-indicator" title="This field is required." aria-label="This field is required.">*</abbr>
</label>
<input class="mds-form__input" type="text" id="full-form-last-name">
</div>
<div class="mds-form__field-group">
<label class="mds-form__label" for="full-form-address">
Address
</label>
<input class="mds-form__input" type="text" id="full-form-adress">
</div>
<div class="mds-form__field-group mds-form__field-group--horizontal">
<div class="mds-form__field-group demo-flex-grow-1">
<label class="mds-form__label" for="full-form-city">
City
</label>
<input class="mds-form__input" type="text" id="full-form-city">
</div>
<div class="mds-form__field-group demo-flex-grow-1">
<label class="mds-form__label" for="full-form-state">
State
</label>
<div class="mds-form__select demo-width-100">
<select class="mds-form__select-input" id="full-form-state">
<option class="mds-form__select-option" value="default">Select your state</option>
<option class="mds-form__select-option" value="just">Just</option>
<option class="mds-form__select-option" value="kidding">Kidding</option>
</select>
<div class="mds-form__select-visual-wrap"></div>
<span class="mds-form__select-open-indicator">
<svg class="mds-icon mds-form__select-open-icon" aria-hidden="true">
<use xlink:href="#caret-down--s">
</use>
</svg>
</span>
</div>
</div>
<div class="mds-form__field-group demo-flex-grow-1">
<label class="mds-form__label" for="full-form-zip">
Zip
</label>
<input class="mds-form__input" type="text" id="full-form-zip">
</div>
</div>
<div class="mds-form__field-group">
<label class="mds-form__label" for="full-form-comments">
Comments
</label>
<textarea class="mds-form__textarea" id="full-form-comments"></textarea>
</div>
</fieldset>
<div class="demo-button-container">
<button class="mds-button mds-button--primary" type="button" disabled>
Submit
</button>
</div>
</form>
<form class="mds-form mds-form--medium-layout" method="post" action="form/processor">
<fieldset class="mds-form__fieldset">
<legend class="mds-form__legend">Address</legend>
<mds-required-fields-key>Required fields</mds-required-fields-key>
<mds-field-group>
<mds-label for="full-form-first-name" required>First Name</mds-label>
<mds-input id="full-form-first-name"></mds-input>
</mds-field-group>
<mds-field-group>
<mds-label for="full-form-last-name" required>Last Name</mds-label>
<mds-input id="full-form-first-name"></mds-input>
</mds-field-group>
<mds-field-group>
<mds-label for="full-form-address">Address</mds-label>
<mds-input id="full-form-address"></mds-input>
</mds-field-group>
<mds-field-group horizontal>
<mds-field-group class="demo-flex-grow-1">
<mds-label for="full-form-city">City</mds-label>
<mds-input id="full-form-city"></mds-input>
</mds-field-group>
<mds-field-group class="demo-flex-grow-1">
<mds-label for="full-form-state">State</mds-label>
<mds-select additional-class="demo-width-100" id="full-form-state" placeholder="Select your state" options='[{"text": "Just", "value": "just"}, {"text": "Kidding", "value": "kidding"}]'>
</mds-select>
</mds-field-group>
<mds-field-group class="demo-flex-grow-1">
<mds-label for="full-form-zip">Zip Code</mds-label>
<mds-input id="full-form-zip"></mds-input>
</mds-field-group>
</mds-field-group>
<mds-field-group>
<mds-label for="full-form-comments">Comments</mds-label>
<mds-textarea id="full-form-comments"></mds-textarea>
</mds-field-group>
</fieldset>
<div class="demo-button-container">
<mds-button variation="primary" disabled>Submit</mds-button>
</div>
</form>
mds-form--medium-layout
modifier class to apply medium form margins to all contained elements.mds-form__field-group--horizontal
modifier class or the horizontal
prop to create a horizontal group of inputs.Some custom styles are required to ensure the proper display of elements within a field group using the mds-form__field-group--horizontal
modifier class or the horizontal
prop:
flex-grow: 1;
property is required for each contained field group to ensure they expand to fill their available space.width: 100%;
property applied to ensure they expand to fill their available space.This example uses large form elements wrapped with a mds-form--large-layout
modifier class to apply margin-based spacing. It uses a Required Fields Key, Labels (default, optional, and required), Inputs, Microcopy, Radio Group, and a Button.
<form class="mds-form mds-form--large-layout" method="post" action="form/processor">
<fieldset class="mds-form__fieldset">
<legend class="mds-form__legend">Sign Up</legend>
<span class="mds-form__required-fields-key mds-form__required-fields-key--large">Required fields</span>
<div class="mds-form__field-group">
<label class="mds-form__label mds-form__label--large" for="full-form-first-name">
First Name
<abbr class="mds-form__label-required-indicator" title="This field is required." aria-label="This field is required.">*</abbr>
</label>
<input class="mds-form__input mds-form__input--large" type="text" id="full-form-first-name">
</div>
<div class="mds-form__field-group mds-form__field-group--error">
<label class="mds-form__label mds-form__label--large" for="full-form-last-name">
Last Name
<abbr class="mds-form__label-required-indicator" title="This field is required." aria-label="This field is required.">*</abbr>
</label>
<input class="mds-form__input mds-form__input--large" type="text" id="full-form-last-name" aria-describedby="full-form-last-name__error">
<span class="mds-form__field-error mds-form__field-error--large" id="full-form-last-name__error" role="alert">
<span class="mds-form__field-error-text">
Please provide your last name.
</span>
</span>
</div>
<div class="mds-form__field-group">
<label class="mds-form__label mds-form__label--large" for="full-form-email__input">
Email<span class="mds-form__label-optional">
(Optional)
</span>
</label>
<span class="mds-form__microcopy mds-form__microcopy--large" id="full-form-email__microcopy">
We’ll never share your email with third parties.
</span>
<input class="mds-form__input mds-form__input--large" type="text" id="full-form-email__input" aria-describedby="full-form-email__microcopy">
</div>
<div class="mds-form__field-group">
<fieldset class="mds-form__radio-button-group mds-form__radio-button-group--large" role="radiogroup">
<legend class="mds-form__radio-button-group-label">
Would you like to sign up for our newsletter?
</legend>
<span class="mds-form__microcopy mds-form__microcopy--large" id="full-form-newsletter__microcopy">
We won’t send you more than one email a week.
</span>
<label class="mds-form__radio-button mds-form__radio-button--large" for="yes,-please.--30532">
<input id="yes,-please.--30532" name="undefined-newsletter" value="blue" type="radio" class="mds-form__radio-button-input" checked aria-describedby="full-form-newsletter__microcopy" />
<span class="mds-form__radio-button-visible-wrap">
<span class="mds-form__radio-button-visual"></span>
<span class="mds-form__radio-button-text ">
Yes, please.
</span>
</span>
</label>
<label class="mds-form__radio-button mds-form__radio-button--large" for="no,-thanks.--47463">
<input id="no,-thanks.--47463" name="undefined-newsletter" value="blue" type="radio" class="mds-form__radio-button-input" aria-describedby="full-form-newsletter__microcopy" />
<span class="mds-form__radio-button-visible-wrap">
<span class="mds-form__radio-button-visual"></span>
<span class="mds-form__radio-button-text ">
No, thanks.
</span>
</span>
</label>
</fieldset>
</div>
</fieldset>
<div class="demo-button-container">
<button class="mds-button mds-button--primary mds-button--large" type="button" disabled>
Sign Up
</button>
</div>
</form>
<form class="mds-form mds-form--large-layout" method="post" action="form/processor">
<fieldset class="mds-form__fieldset">
<legend class="mds-form__legend">Sign Up</legend>
<mds-required-fields-key size="large">Required fields</mds-required-fields-key>
<mds-field-group>
<mds-label for="full-form-first-name" size="large" required>First Name</mds-label>
<mds-input id="full-form-first-name" size="large"></mds-input>
</mds-field-group>
<mds-field-group error>
<mds-label for="full-form-last-name" size="large" required>Last Name</mds-label>
<mds-input aria-describedby="full-form-last-name__error" id="full-form-first-name" size="large"></mds-input>
<mds-field-error id="full-form-last-name__error" size="large" visible>Please provide your last name.</mds-field-error>
</mds-field-group>
<mds-field-group>
<mds-label for="full-form-email__microcopy" size="large" optional>Email</mds-label>
<mds-microcopy id="full-form-email__microcopy" size="large">We’ll never share your email with third parties.</mds-microcopy>
<mds-input aria-describedby="full-form-email__microcopy" id="full-form-address" size="large">
<mds-input>
</mds-field-group>
<mds-field-group>
<mds-radio-button-group size="large" label="Would you like to sign up for our newsletter?">
<mds-microcopy id="full-form-newsletter__microcopy" size="large">We won’t send you more than one email a week.</mds-microcopy>
<mds-radio-button aria-describedby="full-form-newsletter__microcopy" name="radio-group-example" size="large" value="yes" checked> Yes, please. </mds-radio-button>
<mds-radio-button aria-describedby="full-form-newsletter__microcopy" name="radio-group-example" size="large" value="no"> No, thanks. </mds-radio-button>
</mds-radio-button-group>
</mds-field-group>
</fieldset>
<div class="demo-button-container">
<mds-button size="large" variation="primary" disabled>Sign Up</mds-button>
</div>
</form>
mds-form--large-layout
modifier class to apply large form margins to all contained elements.--large
modifier classes or the large
prop values on all form elements to render their large sizes.
Class
|
Applies to
|
Outcome
|
---|---|---|
|
|
Applies margin-based spacing to all contained form elements. |
|
|
Applies margin-based spacing to all contained form elements. |
|
|
Applies margin-based spacing to all contained form elements. |
|
|
Changes the layout of form fields from vertical to horizontal. |
|
|
Applies error styles to form elements. |
Use this mixin to create media queries in your product styles to switch all form elements to their touch variation. Includes styles for:
@include mds-form-all-touch-properties();
For example, switching to the touch variation on screens with a max-width
of 500px
:
// Your product SCSS
@media screen and (max-width: 500px) {
@include mds-form-all-touch-properties();
}
max-width
, pointer: coarse
is another helpful method for targeting touch screen devices.When setting props as attributes on a custom HTML element, use kebab-case
instead of camelCase
.
Prop
|
Type
|
Validation
|
Default
|
Description
|
---|---|---|---|---|
|
String |
— |
— |
A space-separated list of class names that will be appended to the default |
|
Boolean |
— |
|
Applies error styles to form elements. Avoid setting this prop manually, see Additional Behaviors below for more information. |
|
Boolean |
Only applies to |
|
Changes the layout of form fields from vertical to horizontal. |
Pass two or more Form elements (Checkboxes, Field Errors, Inputs, Labels, Microcopy, Radio Buttons, Selects, or Textareas) between the <mds-field-group></mds-field-group>
tags to set the content of the field group.
Field groups automatically synchronize error states across child elements by listening for events triggered by a child Field Error’s show()
and hide()
methods.
mds-field-error-activated
event, the parent field group’s error
prop is set to true
. Inversely, when the Field Error emits the mds-field-error-dismissed
event, the parent field group’s error
prop is set to false
.error
prop is true
, the form element within the field group—for example, an Input—will automatically switch to its visual error state (with the red underline).Using the default slot for contained form elements:
<form class="mds-form mds-form--medium-layout">
<mds-field-group>
<mds-label for="first-name">First Name</mds-label>
<mds-input placeholder="First Name" id="first-name"></mds-input>
<mds-field-error id="first-name-error">Please provide your first name.</mds-field-error>
</mds-field-group>
</form>
label
with each form element.for
attribute on each label
with a value matching the id
attribute on the corresponding Input, Textarea, or Select.placeholder
text to provide an example of the type of input you need from the user. For example, if you need a phone number in a certain format, include (123) 456-7890
as placeholder text.aria-describedby
attribute on each Input, Textarea, or Select that has a Microcopy or a Field Error providing additional information. The value of the aria-describedby
attribute must match the id
attribute on the Microcopy or Field Error.role="alert"
on Field Error components.aria-invalid="true"
to an element where a validation error has occurred.fieldset
and legend
for grouped form elements, such as Radio Buttons and Checkboxes.placeholder
text in place of a label
.