Forms

  • HTML/CSS Available
  • Web Component In Progress (MDS-6404)
  • Last Updated

    2.1.0

Forms gather information from users via Checkboxes, Inputs, Radio Buttons, Selects and Textareas. Labels sit atop these elements.

Examples

Address Form

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.

Address Form
Address Required fields
<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="/icons/mds.svg#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" disabled> Submit </button>
    </div>
</form>

MDS Features

  • Uses the mds-form--medium-layout modifier class to apply medium form margins to all contained elements. See the spacing elements guidelines in the composition section for more information.
  • Uses the mds-form__field-group--horizontal modifier class to create a horizontal group of three inputs. See the grouping elements guidelines in the composition section for more information.

Customizations

Some custom styles are required to ensure the proper display of elements within a mds-form__field-group using the mds-form__field-group--horizontal modifier class:

  • A flex-grow: 1; property is required for each contained element—e.g. mds-form__label, mds-form__input—to ensure they expand to fill their available space.
  • mds-form__select need a width: 100%; property applied to ensure they expand to fill their available space.

Sign Up Form

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.

Sign Up Form
Sign Up Required fields
Please provide your last name.
We’ll never share your email with third parties.
Would you like to sign up for our newsletter? We won’t send you more than one email a week.
<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--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.--2063">
                    <input id="yes,-please.--2063" 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.--56273">
                    <input id="no,-thanks.--56273" 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" disabled> Sign Up </button>
    </div>
</form>

MDS Features

  • Uses the mds-form--large-layout modifier class to apply large form margins to all contained elements. See the spacing elements guidelines in the composition section for more information.
  • Uses --large modifier classes on all form elements to render their large sizes.
  • Radio Group sizing modifier classes must apply to the mds-form__radio-button-group element.

Guidelines

Composition

Form Structure

  • Always wrap form elements within a <form> using the mds-form class.
  • Use semantic HTML form elements, e.g., <fieldset>, <legend>, <label>, and <input>.

Grouping Elements

When constructing forms it is critical to utilize a container with the mds-form__field-group class to group related elements. For example, when pairing a Label with an Input:

<form class="mds-form">
    <div class="mds-form__field-group">
        <label class="mds-form__label" for="input-01">[Label text]</label>
        <input class="mds-form__input" id="input-01">
    </div>
</form>

If a form field includes Microcopy and/or an error, always place these elements within the mds-form__field-group container wrapping the relevant field. For example:

<form class="mds-form">
    <div class="mds-form__field-group">
        <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" id="input-01" aria-describedby="input-01-microcopy input-01-error">
        <span class="mds-form__field-error" id="input-01-error" role="alert">[Error text]</span>
    </div>
</form>
  • Multiple pieces of descriptive text, like microcopy and an error, can be linked to a single element by placing multiple id in an element's aria-describedby attribute. See accessibility guidelines for more information.

To create a horizontal group of form elements, wrap multiple mds-form__field-group containers within a parent mds-form__field-group container and apply the mds-form__field-group--horizontal modifier class. For example:

<form class="mds-form">
    <div class="mds-form__field-group mds-form__field-group--horizontal">
        <div class="mds-form__field-group">[Label, input and other elements.]</div>
        <div class="mds-form__field-group">[Label, input and other elements.]</div>
        <div class="mds-form__field-group">[Label, input and other elements.]</div>
    </div>
</form>

If multiple elements within a form are deeply related, like fields for entering an address, always wrap them in a container with the mds-form__fieldset class and include a descriptive legend using mds-form__legend. For example:

<form class="mds-form">
    <fieldset class="mds-form__fieldset">
        <legend class="mds-form__legend">[Description of fieldset content for screen readers.]</legend>
        <div class="mds-form__field-group">[Address]</div>
        <div class="mds-form__field-group">[City]</div>
        <div class="mds-form__field-group">[State]</div>
        <div class="mds-form__field-group">[Zip Code]</div>
    </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.

Spacing Elements

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--medium-layout"> [Insert medium form element markup here.] </form>

Layout modifier classes only apply spacing to elements, you must still apply sizing modifier classes to each individual element within the form. For example, to use the mds-form--large-layout modifier class:

<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" 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" 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">[Microcopy text]</span>
        <input class="mds-form__input mds-form__input--large" id="email" aria-describedby="email-microcopy">
    </div>
</form>
  • Layout modifier classes apply margin-right to elements contained within an .mds-form__field-group--horizontal container.
  • Always use form elements of the same size as the layout modifier class used to avoid undesirable spacing.

Accessibility

  • Always include a label with each form element.
  • Include a for attribute on each label with a value matching the id attribute on the corresponding input, textarea or select.
  • Use 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.
  • Never use placeholder text in place of a label.
  • Include an aria-describedby attribute on each input, textarea, or select that has an .mds-form__microcopy or an .mds-form__field-error component providing additional information. The value of the aria-describedby attribute must match the id attribute on the .mds-form__microcopy or .mds-form__field-error component.
  • Always include role="alert" on .mds-form__field-error components.
  • Form labels must always be visible.
  • Add aria-invalid="true" to an element where a validation error has occurred.
  • Ensure all form elements are keyboard accessible.
  • Use fieldset and legend for grouped form elements, such as radio buttons and checkboxes.

Code Reference

CSS Class References

Class
Applies to
Outcome

mds-form--small-layout

mds-form

Applies margin-based spacing to all contained form elements.

mds-form--medium-layout

mds-form

Applies margin-based spacing to all contained form elements.

mds-form--large-layout

mds-form

Applies margin-based spacing to all contained form elements.

mds-form__field-group--horizontal

mds-form__field-group

Changes the layout of form fields from vertical to horizontal.

mds-form--error

mds-form__field-group

Applies error styles to form elements.

©2019 Morningstar, Inc. All rights reserved. Terms of Use