Skip to main content

Field Component

The field module facilitates the layout of a form control and its associated label, plus any other applicable text or sub-controls (e.g. error text or help button).

Unstacked Field

The field__label & field__control elements are inline by default, taking up only as much horizontal space as they need.

Multiple fields can be laid out inline by using the span tag with field class, as per the example below.

<span class="field">
  <label class="field__label" for="field1"> Field 1 </label>
  <span class="field__control textbox">
    <input
      class="textbox__control"
      id="field1"
      type="text"
      placeholder="placeholder text"
    />
  </span>
</span>
<span class="field">
  <label class="field__label" for="field2"> Field 2 </label>
  <span class="field__control">
    <span class="select">
      <select name="field2" id="field2">
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
        <use href="#icon-chevron-down-12" />
      </svg>
    </span>
  </span>
</span>
<span class="field">
  <label class="field__label" for="field3"> Field 3 </label>
  <span class="field__control switch">
    <input
      aria-label="Switch Demo"
      class="switch__control"
      role="switch"
      type="checkbox"
      id="field3"
    />
    <span class="switch__button" />
  </span>
</span>

Replace the span tag with a div tag to layout unstacked fields in blocks, as per the following example.

<div class="field">
  <label class="field__label" for="field1"> Field 1 </label>
  <span class="field__control textbox">
    <input
      class="textbox__control"
      id="field1"
      type="text"
      placeholder="placeholder text"
    />
  </span>
</div>
<div class="field">
  <label class="field__label" for="field2"> Field 2 </label>
  <span class="field__control">
    <span class="select">
      <select name="field2" id="field2">
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
        <use href="#icon-chevron-down-12" />
      </svg>
    </span>
  </span>
</div>
<div class="field">
  <label class="field__label" for="field3"> Field 3 </label>
  <span class="field__control switch">
    <input
      aria-label="Switch Demo"
      class="switch__control"
      role="switch"
      type="checkbox"
      id="field3"
    />
    <span class="switch__button" />
  </span>
</div>

For a textarea, the label will be vertically aligned to the middle of the field by default. Apply the field--align-top modifier to align it to the top.

<span class="field field--align-top">
  <label class="field__label" for="field-textarea-1"> Field 1 </label>
  <span class="field__control textbox">
    <textarea class="textbox__control" id="field-textarea-1" />
  </span>
</span>

Stacked Field

For a label stacked above the control, use the field__label--stacked element modifier.

Again, multiple fields can be laid out inline by using a span tag, as per the example below.

<span class="field">
  <label class="field__label field__label--stacked" for="field1">
    Field 1
  </label>
  <span class="textbox">
    <input
      class="textbox__control"
      id="field1"
      type="text"
      placeholder="placeholder text"
    />
  </span>
</span>
<span class="field">
  <label class="field__label field__label--stacked" for="field2">
    Field 2
  </label>
  <span class="field__control">
    <span class="select">
      <select name="field2" id="field2">
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
        <use href="#icon-chevron-down-12" />
      </svg>
    </span>
  </span>
</span>
<span class="field">
  <label class="field__label field__label--stacked"> Field 3 </label>
  <span class="field__control switch">
    <input
      aria-label="Switch Demo"
      class="switch__control"
      role="switch"
      type="checkbox"
      id="field3"
    />
    <span class="switch__button" />
  </span>
</span>

Replace the span tag with a div tag to layout the stacked fields in blocks, as per the example below.

<div class="field">
  <label class="field__label field__label--stacked" for="field1">
    Field 1
  </label>
  <span class="textbox">
    <input
      class="textbox__control"
      id="field1"
      type="text"
      placeholder="placeholder text"
    />
  </span>
</div>
<div class="field">
  <label class="field__label field__label--stacked" for="field2">
    Field 2
  </label>
  <span class="field__control">
    <span class="select">
      <select name="field2" id="field2">
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
        <use href="#icon-chevron-down-12" />
      </svg>
    </span>
  </span>
</div>
<span class="field">
  <label class="field__label field__label--stacked"> Field 3 </label>
  <span class="field__control switch">
    <input
      aria-label="Switch Demo"
      class="switch__control"
      role="switch"
      type="checkbox"
      id="field3"
    />
    <span class="switch__button" />
  </span>
</span>

Field Font-Size

The field label will honour any font-size cascade. Wrap the label and control in a field__group element to maintain vertical alignment.

NOTE : form controls do not inherit the font-size cascade. This is default browser behaviour.

<span class="field" style="font-size: 18px">
  <span class="field__group">
    <label class="field__label" for="email"> Field 1 </label>
    <span class="field__control textbox">
      <input
        class="textbox__control"
        id="field1"
        type="text"
        placeholder="placeholder text"
      />
    </span>
  </span>
</span>
<span class="field" style="font-size: 18px">
  <span class="field__group">
    <label class="field__label" for="size"> Field 2 </label>
    <span class="field__control">
      <span class="select">
        <select name="size" id="size">
          <option value="1">Option 1</option>
          <option value="2">Option 2</option>
          <option value="3">Option 3</option>
        </select>
        <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
          <use href="#icon-chevron-down-12" />
        </svg>
      </span>
    </span>
  </span>
</span>
<span class="field" style="font-size: 18px">
  <span class="field__group">
    <label class="field__label" for="field3"> Field 3 </label>
    <span class="field__control switch">
      <input
        aria-label="Switch Demo"
        class="switch__control"
        role="switch"
        type="checkbox"
        id="field3"
      />
      <span class="switch__button" />
    </span>
  </span>
</span>

Disabled Field

The disabled control is conveyed using the disabled attribute. The value of a disabled control is not passed to the server.

<span class="field">
  <label class="field__label field__label--disabled" for="email">
    Field 1
  </label>
  <span class="field__control textbox">
    <input
      class="textbox__control"
      id="field1"
      type="text"
      value="placeholder text"
      disabled
    />
  </span>
</span>
<span class="field">
  <label class="field__label field__label--disabled" for="size">
    Field 2
  </label>
  <span class="field__control">
    <span class="select">
      <select name="field2" id="field2" disabled>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
        <use href="#icon-chevron-down-12" />
      </svg>
    </span>
  </span>
</span>
<span class="field">
  <label class="field__label field__label--disabled" for="field3">
    Field 3
  </label>
  <span class="field__control switch">
    <input
      disabled
      aria-label="Switch Demo"
      class="switch__control"
      role="switch"
      type="checkbox"
      id="field3"
    />
    <span class="switch__button" />
  </span>
</span>

TIP: Disabled controls are exempt from WCAG colour contrast requirements .

Readonly Field

A readonly control is conveyed using the readonly attribute. The value of a readonly control is passed to the server.

<span class="field">
  <label class="field__label" for="email"> Field 1 </label>
  <span class="field__control textbox">
    <input
      class="textbox__control"
      id="field1"
      type="text"
      value="placeholder text"
      readonly
    />
  </span>
</span>
<span class="field">
  <label class="field__label" for="size"> Field 2 </label>
  <span class="field__control">
    <span class="select">
      <select name="field2" id="field2">
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
        <use href="#icon-chevron-down-12" />
      </svg>
    </span>
  </span>
</span>

Required Field

A required field is conveyed visually with an asterisk, and non-visually using the aria-required property.

<span class="field">
  <label class="field__label" for="email">
    Field 1 ${" "}
    <sup> * </sup>
  </label>
  <span class="field__control textbox">
    <input
      aria-required="true"
      class="textbox__control"
      id="field1"
      type="text"
      placeholder="placeholder text"
    />
  </span>
</span>
<span class="field">
  <label class="field__label" for="size">
    Field 2 ${" "}
    <sup> * </sup>
  </label>
  <span class="field__control">
    <span class="select">
      <select aria-required="true" id="field2">
        <option value="0" disabled selected>-select-</option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
        <use href="#icon-chevron-down-12" />
      </svg>
    </span>
  </span>
</span>

Invalid Field

An invalid control is conveyed visually via a combination of red outline and some other indicator (usually either text and/or an icon). The invalid state is conveyed non-visually using the aria-invalid state.

IMPORTANT: The example below shows the field with red border only. Do not forget that colour should not be used as the only visual means of conveying information . A description and/or icon is also required. See next section for more details.

<span class="field">
  <label class="field__label" for="email"> Field 1 </label>
  <span class="field__control textbox">
    <input
      aria-invalid="true"
      class="textbox__control"
      id="field1"
      type="text"
      placeholder="placeholder text"
    />
  </span>
</span>
<span class="field">
  <label class="field__label" for="size"> Field 2 </label>
  <span class="field__control">
    <span class="select">
      <select aria-invalid="true" id="field2">
        <option value="0" disabled selected>-select-</option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
      </select>
      <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
        <use href="#icon-chevron-down-12" />
      </svg>
    </span>
  </span>
</span>

Field Description

A field may have nearby text to describe additional instructions, status or validation error of the control.

The field__description element defines some minimal styling, but does not dictate location or layout. This element has modifiers for confirmation , information and attention , depending on the type of descriptive text (or icon).

TIP: The description element can be designated as an ARIA live-region if client-side updates occur.

Text on Side of Field

A description can be placed adjacent to any stacked or unstacked field simply by using an inline-level tag, such as span.

Field description or error
<span class="field">
  <label class="field__label" for="field1"> Field 1 </label>
  <span class="field__control textbox">
    <input
      aria-describedby="field1-description"
      class="textbox__control"
      id="field1"
      type="text"
    />
  </span>
  <span class="field__description" id="field1-description">
    <span> Field description or error </span>
  </span>
</span>

To change the type of decription you would use field__description--confirmation , field__description--information , or field__description--attention .

Field description - default
Field description - confirmation
Field description - information
Field description - error (attention)

Text Below Stacked Field

A description can be placed underneath a stacked field simply by using a block-level tag, such as div.

Field description or error
<span class="field">
  <label class="field__label field__label--stacked" for="field1">
    Field 1
  </label>
  <div class="field__control textbox">
    <input
      aria-describedby="field1-description"
      class="textbox__control"
      id="field1"
      type="text"
    />
  </div>
  <div class="field__description" id="field1-description">
    <span> Field description or error </span>
  </div>
</span>

Text Above or Below Unstacked Field

A description can be added directly above and/or below the control by utlising CSS table-layout via the field--table modifier and field__row elements.

Field description or error
<span class="field field--table">
  <div class="field__row">
    <span>
      <!-- empty cell-->
    </span>
    <span class="field__description" id="field1-description">
      <span> Field description or error </span>
    </span>
  </div>
  <div class="field__row">
    <label class="field__label" for="field1"> Field Label </label>
    <span class="textbox">
      <input
        aria-describedby="field1-description"
        class="textbox__control"
        id="field1"
        type="text"
      />
    </span>
  </div>
</span>

Text Below Floating label

When you use a floating label, you can have the description text below

Field description or error
<span class="field floating-label">
  <label class="floating-label__label" for="field1"> Field 1 </label>
  <div class="field__control textbox">
    <input
      aria-describedby="field1-description"
      class="textbox__control"
      id="field1"
      type="text"
    />
  </div>
  <div class="field__description" id="field1-description">
    <span> Field description or error </span>
  </div>
</span>

Listbox Button with Label in Error State

You can use a listbox button as a field. This example includes a label, the listbox button as well an error message with the entire thing in an error state.

Red
Blue
Yellow
Green
There was an error
<span class="field">
  <label
    class="field__label field__label--stacked"
    for="field-listbox-button-1"
  >
    Listbox Button 1
  </label>
  <div class="field__control textbox">
    <span
      class="listbox-button listbox-button--form listbox-button--error"
      data-makeup-auto-select="false"
    >
      <button
        class="btn btn--form"
        style="min-width: 150px"
        aria-expanded="false"
        aria-haspopup="listbox"
        aria-describedby="field-listbox-button-1-description"
      >
        <span class="btn__cell">
          <span class="btn__label"> Color: </span>
          <span class="btn__text"> - </span>
          <svg class="icon icon--12" height="10" width="14" aria-hidden="true">
            <use href="#icon-chevron-down-12" />
          </svg>
        </span>
      </button>
      <div class="listbox-button__listbox">
        <div class="listbox-button__options" role="listbox">
          <div class="listbox-button__option" role="option">
            <span class="listbox-button__value"> Red </span>
            <svg class="icon icon--16" height="10" width="14">
              <use href="#icon-tick-16" />
            </svg>
          </div>
          <div class="listbox-button__option" role="option">
            <span class="listbox-button__value"> Blue </span>
            <svg class="icon icon--16" height="10" width="14">
              <use href="#icon-tick-16" />
            </svg>
          </div>
          <div
            class="listbox-button__option"
            role="option"
            aria-disabled="true"
          >
            <span class="listbox-button__value"> Yellow </span>
            <svg class="icon icon--16" height="10" width="14">
              <use href="#icon-tick-16" />
            </svg>
          </div>
          <div class="listbox-button__option" role="option">
            <span class="listbox-button__value"> Green </span>
            <svg class="icon icon--16" height="10" width="14">
              <use href="#icon-tick-16" />
            </svg>
          </div>
        </div>
      </div>
      <select id="field-listbox-button-1" hidden class="listbox__native">
        <option value="1" />
        <option value="2" />
        <option value="3" />
        <option value="4" />
      </select>
    </span>
  </div>
  <div
    class="field__description field__description--attention"
    id="field-listbox-button-1-description"
  >
    <svg class="icon icon--16" height="10" width="14" aria-hidden="true">
      <use href="#icon-attention-filled-16" />
    </svg>
    <span> There was an error </span>
  </div>
</span>

Textbox in Error State

You can use a textbox in an error state. This example includes a label, the textbox as well an error message with the entire thing in an error state.

There was an error

Textbox in Error State

You can use a textbox in an error state. This example includes a label, the textbox as well an error message with the entire thing in an error state.

<span class="field">
  <label class="field__label field__label--stacked" for="field-textbox-1">
    Textbox 1
  </label>
  <div class="field__control textbox">
    <input
      aria-describedby="field-textbox-1-description"
      class="textbox__control"
      id="field-textbox-1"
      type="text"
      aria-invalid="true"
    />
  </div>
  <div
    class="field__description field__description--attention"
    id="field-textbox-1-description"
  >
    <svg class="icon icon--16" height="10" width="14" aria-hidden="true">
      <use href="#icon-attention-filled-16" />
    </svg>
    <span> There was an error </span>
  </div>
</span>

Fluid Field

Form control elements (such as select and input ) are inline-block by default, and will only use up as much of their parent's horizontal space as they need.

For a stacked field the control must be set to 100% width (using the fluid utility class) to fill all available space.

<div class="field-group">
  <span class="field fluid">
    <label class="field__label field__label--stacked" for="field1">
      Field 1
    </label>
    <div class="field__control textbox">
      <input
        class="textbox__control fluid"
        id="field1"
        name="field1"
        type="text"
        placeholder="placeholder text"
      />
    </div>
  </span>
  <span class="field fluid">
    <label class="field__label field__label--stacked" for="field2">
      Field 2
    </label>
    <div class="field__control fluid">
      <div class="select select--fluid">
        <select name="field2" id="field2">
          <option value="1">Option 1</option>
          <option value="2">Option 2</option>
          <option value="3">Option 3</option>
        </select>
        <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
          <use href="#icon-chevron-down-12" />
        </svg>
      </div>
    </div>
  </span>
</div>

The above example shows the fields in a flexbox layout. This layout is created using the field-group helper class. Notice that each field is also set to fluid, in order to fill all available flexbox space (flexbox layout takes care of dividing the space evenly between fluid fields).

If we set the form control width to 100% in an unstacked field, the control would flow to a new line below the label (effectively behaving like a stacked label). This behaviour can be avoided by adding an additional field__group element to create flex layout inside of the field.

<div class="field-group">
  <span class="field fluid">
    <span class="field__group fluid">
      <label class="field__label no-wrap" for="field1"> Field 1 </label>
      <span class="field__control fluid textbox">
        <input
          class="textbox__control fluid"
          id="field1"
          type="text"
          placeholder="placeholder text"
        />
      </span>
    </span>
  </span>
  <span class="field fluid">
    <span class="field__group fluid">
      <label class="field__label no-wrap" for="field2"> Field 2 </label>
      <span class="field__control fluid">
        <span class="select select--fluid">
          <select name="field2" id="field2">
            <option value="1">Option 1</option>
            <option value="2">Option 2</option>
            <option value="3">Option 3</option>
          </select>
          <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
            <use href="#icon-chevron-down-12" />
          </svg>
        </span>
      </span>
    </span>
  </span>
</div>

TIP: You may want to experiment with sizes other than 100%, and also the flexbox justify-content property.

For a fluid control and description, those elements can be wrapped in a field__group container to create flex layout.

Field description or error
Field description or error
<div class="field-group">
  <span class="field fluid">
    <label
      class="field__label field__label--stacked"
      for="field1-fluid-block-1"
    >
      Field 1
    </label>
    <div class="field__group">
      <span class="field__control textbox fluid">
        <input
          class="textbox__control fluid"
          id="field1"
          type="text"
          placeholder="placeholder text"
        />
      </span>
      <span class="field__description">
        <span> Field description or error </span>
      </span>
    </div>
  </span>
  <span class="field fluid">
    <label class="field__label field__label--stacked" for="field2">
      Field 2
    </label>
    <div class="field__group">
      <div class="field__control fluid">
        <div class="select select--fluid">
          <select name="field-fluid-block-2" id="field2">
            <option value="1">Option 1</option>
            <option value="2">Option 2</option>
            <option value="3">Option 3</option>
          </select>
          <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
            <use href="#icon-chevron-down-12" />
          </svg>
        </div>
      </div>
      <span class="field__description">
        <span> Field description or error </span>
      </span>
    </div>
  </span>
</div>

Field Character Count

A field may have a character count section typically under the input and aligned to the right.

This variant adds a top-level container that houses both the field description and the character count, though field description or error is not necessary.

In order to be accessible, the character count should have a clipped element to describe what it is. At the same time, aria-describedby should be added to the input element that points to the character count element. Finally, aria-live should be off by default, but if it passes the current max characters, then it should be changed to polite. Once it goes back down below the max, it should go back to off.

Field with Character Count Only

Character character can be added by utlising CSS grid via the field__description--group modifier and the addition of the relevant markup. By default if there is only one element in the group, it will align to the right

0 of 140 charaters
<span class="field">
  <label
    class="field__label field__label--stacked"
    for="field-character-2-input"
  >
    Field 2
  </label>
  <span class="field__control textbox">
    <input
      type="text"
      aria-describedby="field-character-2"
      class="textbox__control"
      id="field-character-2-input"
      aria-live="off"
    />
  </span>
  <div class="field__description field__description--group">
    <span id="field-character-2">
      0 of 140 ${" "}
      <span class="clipped"> charaters </span>
    </span>
  </div>
</span>

Field Description and Character Count

A field description (or error) and character count can be added by adding an element before the field count. It will left align the description and right align the character count.

Field description or error0 of 140 charaters
<span class="field">
  <label
    class="field__label field__label--stacked"
    for="field-character-2-input"
  >
    Field 2
  </label>
  <span class="field__control textbox">
    <input
      type="text"
      aria-describedby="field-describe-3 field-character-3"
      class="textbox__control"
      aria-live="off"
    />
  </span>
  <div class="field__description field__description--group">
    <span id="field-describe-3"> Field description or error </span>
    <span id="field-character-3">
      0 of 140 ${" "}
      <span class="clipped"> charaters </span>
    </span>
  </div>
</span>

Field Description and Character Count with Text area

A field description (or error) and character count can also be added to a text area. Use similar markup as before but add a textarea element.

Field description or error0 of 140 charaters
<span class="field">
  <label class="field__label field__label--stacked" for="field-textarea-2">
    Field 2
  </label>
  <span class="field__control textbox">
    <textarea
      class="textbox__control"
      id="field-textarea-2"
      aria-describedby="field-describe-4 field-character-4"
      aria-live="off"
    />
  </span>
  <div class="field__description field__description--group">
    <span id="field-describe-4"> Field description or error </span>
    <span id="field-character-4">
      0 of 140 ${" "}
      <span class="clipped"> charaters </span>
    </span>
  </div>
</span>