Floating Label Component

Floating Label with no Value

If the textbox has no value, the label can be positioned inside the textbox.

<span class="floating-label">
  <label class="floating-label__label" for="first-name"> First Name </label>
  <span class="textbox">
    <input class="textbox__control" id="first-name" type="text" />
  </span>
</span>

Floating Label with Value

If the textbox has a value, the label must be positioned above the textbox.

<span class="floating-label">
  <label class="floating-label__label" for="last-name"> Last Name </label>
  <span class="textbox">
    <input class="textbox__control" id="last-name" type="text" value="Smith" />
  </span>
</span>

Large floating label

<span class="floating-label floating-label--large">
  <label class="floating-label__label" for="dob"> Date Of Birth </label>
  <span class="textbox">
    <input class="textbox__control" id="dob" type="text" />
  </span>
</span>

Floating Label with Disabled Textbox

Use the disabled property & floating-label__label--disabled modifier on the input element and the label element respectively to disable the input.

<span class="floating-label">
  <label
    class="floating-label__label floating-label__label--disabled"
    for="first-name"
  >
    First Name
  </label>
  <span class="textbox textbox--disabled">
    <input class="textbox__control" id="first-name" type="text" disabled />
  </span>
</span>

Floating Label with Placeholder

The placeholder should only be shown when the textbox is focused and there is no text

<span class="floating-label">
  <label class="floating-label__label" for="first-name"> First Name </label>
  <span class="textbox">
    <input
      class="textbox__control"
      id="first-name"
      type="text"
      placeholder="No spaces or numbers allowed"
    />
  </span>
</span>

Floating Label with Invalid Textbox

Set the aria-invalid property to true and add floating-label__label--invalid to the label to semantically and visually highlight the invalid state.

<span class="floating-label">
  <label
    class="floating-label__label floating-label__label--invalid"
    for="first-name"
  >
    First Name
  </label>
  <span class="textbox textbox--invalid">
    <input
      class="textbox__control"
      id="first-name"
      type="text"
      aria-invalid="true"
    />
  </span>
</span>

Floating Label with Textarea

Use the textarea tag for a multi-line textbox.

A multi-line textbox allows line breaks and has a minimum height of 200px.

In order to prevent overlap for floating label, use .floating-label--opaque class

<span class="floating-label floating-label--opaque">
  <label class="floating-label__label" for="first-name">
    Enter list of users
  </label>
  <span class="textbox">
    <textarea aria-label="Textbox demo" class="textbox__control" />
  </span>
</span>

Floating label with Combobox

Use the textarea tag for a multi-line textbox.

A multi-line textbox allows line breaks and has a minimum height of 200px.

Option 1
Option 2
Option 3
<span class="combobox floating-label">
  <label class="floating-label__label" for="first-name">
    Enter list of users
  </label>
  <span class="combobox__control">
    <input
      name="combobox-default"
      id="first-name"
      role="combobox"
      type="text"
      aria-haspopup="listbox"
      aria-label="Combobox demo"
      aria-owns="listbox1"
    />
    <svg class="icon icon--12" height="8" width="8" aria-hidden="true">
      <use href="#icon-chevron-down-12" />
    </svg>
  </span>
  <div class="combobox__listbox">
    <div id="listbox1" class="combobox__options" role="listbox">
      <div class="combobox__option" role="option">
        <span> Option 1 </span>
      </div>
      <div class="combobox__option" role="option">
        <span> Option 2 </span>
      </div>
      <div class="combobox__option" role="option">
        <span> Option 3 </span>
      </div>
    </div>
  </div>
</span>

Floating Label with long text

This example shows how the floating label will truncate with long text

<span class="floating-label">
  <label class="floating-label__label" for="first-name">
    Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
  </label>
  <span class="textbox">
    <input class="textbox__control" id="first-name" type="text" />
  </span>
</span>

Floating Label with select

<span class="floating-label">
  <label class="floating-label__label"> Select Option </label>
  <span class="select">
    <select name="options">
      <option value="">Choose an option</option>
      <option value="item1">Pick Option 1 (default)</option>
      <option value="item2">Pick Option 2</option>
      <option value="item3">Pick 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>

Floating Label with large select

<span class="floating-label floating-label--large">
  <label class="floating-label__label"> Select Option </label>
  <span class="select select--large">
    <select name="options">
      <option value="">Choose an option</option>
      <option value="item1">Pick Option 1</option>
      <option value="item2">Pick Option 2</option>
      <option value="item3">Pick 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>

Floating Label with Phone input

For phone input, the label always remains in floating state above the input. This state ensures that the label does not obscure the phone number.

Albania(+355)
India(+91)
Saint Helena, Ascension and Tristan da Cunha(+290)
United Kingdom(+44)
United States of America(+1)
+1
<span class="phone-input">
  <span class="listbox-button listbox-button--form">
    <button
      class="btn btn--form btn--split-start"
      aria-expanded="false"
      aria-haspopup="listbox"
      type="button"
      data-listbox-button-prefix="Country: "
    >
      <span class="btn__cell">
        <span class="btn__text">
          <svg
            class="flag flag--us"
            height="18"
            width="24"
            aria-hidden="true"
            data-country-code="1"
          >
            <use href="#flag-us" />
          </svg>
        </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">
            <svg
              class="flag flag--al"
              height="18"
              width="24"
              aria-hidden="true"
              data-country-code="355"
            >
              <use href="#flag-al" />
            </svg>
            <span> Albania </span>
            <span> (+355) </span>
          </span>
          <svg class="icon icon--16" height="10" width="14" aria-hidden="true">
            <use href="#icon-tick-16" />
          </svg>
        </div>
        ...
        <div class="listbox-button__option" role="option" aria-selected="true">
          <span class="listbox-button__value">
            <svg
              class="flag flag--us"
              height="18"
              width="24"
              aria-hidden="true"
              data-country-code="1"
            >
              <use href="#flag-us" />
            </svg>
            <span> United States of America </span>
            <span> (+1) </span>
          </span>
          <svg class="icon icon--16" height="10" width="14" aria-hidden="true">
            <use href="#icon-tick-16" />
          </svg>
        </div>
      </div>
    </div>
  </span>
  <span class="field floating-label">
    <label class="floating-label__label" for="field1">
      <span class="clipped"> Area code + </span>
      Phone Number
    </label>
    <span class="textbox">
      <span id="floating-phone-prefix-0"> +1 </span>
      <input
        class="textbox__control"
        type="tel"
        aria-label="area code + phone number"
        autocomplete="tel-national"
        aria-describedby="floating-phone-prefix-0"
      />
    </span>
  </span>
</span>

Floating Label Transitions

By default, with only the base markup shown above, the label remains in a floating state above the input. This default state ensures that the label does not obscure the textbox value while we wait for JavaScript.

When JavaScript is ready, the label can be re-positioned inside the textbox by adding the floating-label__label--inline modifier class. By default, this re-positioning of label happens instantly, without a transition. Typically, we do not want to show transitions on the initial page render, as this might be too jarring and distracting for some users.

You will also need to add the floating-label__label--focus class when the input recieves focus and remove it when the input loses focus. This is to ensure the right colors are applied to the label when focusing the input.

To opt into transitions after the initial render is complete, add the floating-label__label--animate modifier when the textbox receives focus.

The examples above use makeup-floating-label , a simple JavaScript module that adds the aforementioned logic. Feel free to use this module or use it as the basis to roll your own.