Skip to main content Skip to docs navigation

Floating Labels

Create elegant, space-efficient form controls with animated floating labels that enhance usability and maintain visual hierarchy.

Overview

Floating labels in Chassis CSS provide an intuitive way to improve form usability while preserving space. As users interact with the form, labels smoothly transition from placeholder positions to floating above the input, keeping context visible at all times.

Chassis CSS implements floating labels using pure CSS, leveraging the :placeholder-shown pseudo-element and sibling selectors for smooth animations without JavaScript dependencies.

Basic usage

To implement floating labels, wrap a <label> and form control (with .form-input class) inside a .form-floating container. The structure requires:

  1. The form control must come before the label in the markup
  2. Each input requires a placeholder attribute
  3. Each label must be properly associated with its form control using the for attribute

Example

html
<div class="form-floating mb-medium">
  <input type="email" class="form-input" id="floatingInput" placeholder="name@example.com">
  <label for="floatingInput">Email address</label>
</div>
<div class="form-floating">
  <input type="password" class="form-input" id="floatingPassword" placeholder="Password">
  <label for="floatingPassword">Password</label>
</div>

Pre-filled values

When there's a value already defined, <label>s will automatically adjust to their floated position.

html
<div class="form-floating">
  <input type="email" class="form-input" id="floatingInputValue" placeholder="name@example.com" value="test@example.com">
  <label for="floatingInputValue">Input with value</label>
</div>

Form validation

Form validation styles work seamlessly with floating labels.

html
<div class="form-floating">
  <input type="email" class="form-input is-invalid" id="floatingInputInvalid" placeholder="name@example.com" value="test@example.com">
  <label for="floatingInputInvalid">Invalid input</label>
</div>

Textarea

By default, <textarea> elements with .form-input will be the same height as <input>s.

html
<div class="form-floating">
  <textarea class="form-input" placeholder="Share your thoughts here" id="floatingTextarea"></textarea>
  <label for="floatingTextarea">Comments</label>
</div>

To set a custom height on your <textarea>, do not use the rows attribute. Instead, set an explicit height using inline style or custom CSS.

html
<div class="form-floating">
  <textarea class="form-input" placeholder="Share your thoughts here" id="floatingTextarea2" style="height: 100px"></textarea>
  <label for="floatingTextarea2">Comments</label>
</div>

Select

Floating labels also work with .form-select elements. Unlike inputs, select menus will always show the <label> in its floated state.

html
<div class="form-floating">
  <select class="form-select" id="floatingSelect" aria-label="Floating label select example">
    <option selected>Choose an option</option>
    <option value="1">Option One</option>
    <option value="2">Option Two</option>
    <option value="3">Option Three</option>
  </select>
  <label for="floatingSelect">Preferences</label>
</div>

Select elements with size and multiple attributes are not supported with floating labels.

Disabled inputs

Add the disabled boolean attribute to inputs, textareas, or selects to apply the disabled state styling—grayed out appearance, no pointer events, and focus prevention.

html
<div class="form-floating mb-medium">
  <input type="email" class="form-input" id="floatingInputDisabled" placeholder="name@example.com" disabled>
  <label for="floatingInputDisabled">Email address</label>
</div>
<div class="form-floating mb-medium">
  <textarea class="form-input" placeholder="Share your thoughts here" id="floatingTextareaDisabled" disabled></textarea>
  <label for="floatingTextareaDisabled">Comments</label>
</div>
<div class="form-floating mb-medium">
  <textarea class="form-input" placeholder="Share your thoughts here" id="floatingTextarea2Disabled" style="height: 100px" disabled>This textarea is disabled with existing content</textarea>
  <label for="floatingTextarea2Disabled">Comments</label>
</div>
<div class="form-floating">
  <select class="form-select" id="floatingSelectDisabled" aria-label="Floating label disabled select example" disabled>
    <option selected>Choose an option</option>
    <option value="1">Option One</option>
    <option value="2">Option Two</option>
    <option value="3">Option Three</option>
  </select>
  <label for="floatingSelectDisabled">Preferences</label>
</div>

Readonly plaintext inputs

Use the .form-input-plaintext class with floating labels to toggle between editable inputs and plaintext values without affecting your layout.

html
<div class="form-floating mb-medium">
  <input type="email" readonly class="form-input plaintext" id="floatingEmptyPlaintextInput" placeholder="name@example.com">
  <label for="floatingEmptyPlaintextInput">Empty input</label>
</div>
<div class="form-floating mb-medium">
  <input type="email" readonly class="form-input plaintext" id="floatingPlaintextInput" placeholder="name@example.com" value="user@chassis.css">
  <label for="floatingPlaintextInput">Input with value</label>
</div>

File inputs

File inputs can also be used with floating labels, though the visual appearance is different from other input types due to the browser's implementation of file inputs.

File inputs with floating labels may appear differently across browsers. For more consistent styling, consider custom file input implementations.

html
<div class="form-floating">
  <input type="file" class="form-input" id="floatingFileInput" placeholder="Select a file">
  <label for="floatingFileInput">Upload document</label>
</div>

Input groups

Floating labels work with input groups for more complex form layouts.

@
html
<div class="input-group mb-medium">
  <span class="input-addon">@</span>
  <div class="form-floating">
    <input type="text" class="form-input" id="floatingInputGroup1" placeholder="Username">
    <label for="floatingInputGroup1">Username</label>
  </div>
</div>

Always place form helps and form feedbacks outside of the .input-group container to ensure proper styling and positioning.

@
Please choose a username.
html
<div>
  <div class="input-group">
    <span class="input-addon">@</span>
    <div class="form-floating">
      <input type="text" class="form-input is-invalid" id="floatingInputGroup2" placeholder="Username" required>
      <label for="floatingInputGroup2">Username</label>
    </div>
  </div>
  <div class="invalid-feedback">
    Please choose a username.
  </div>
</div>

Icon integration

Enhance your form inputs with icons using the .icon-addon class in combination with .input-addon class for proper positioning.

html
<div class="input-group mb-medium">
  <span class="input-addon icon-addon"><svg class="icon"><use xlink:href="#lock-solid"></use></svg></span>
  <div class="form-floating">
    <input type="password" class="form-input" id="floatingInputGroup3" placeholder="Password">
    <label for="floatingInputGroup3">Password</label>
  </div>
  <button type="button" class="input-addon icon-addon" aria-label="Show password">
    <svg class="icon"><use xlink:href="#eye-solid"></use></svg>
  </button>
</div>

Grid layout

When working with responsive designs, combine floating labels with Chassis CSS's grid system by placing .form-floating containers within column classes:

html
<div class="row g-medium">
  <div class="medium:col">
    <div class="form-floating">
      <input type="email" class="form-input" id="floatingInputGrid" placeholder="name@example.com" value="user@chassis.css">
      <label for="floatingInputGrid">Email address</label>
    </div>
  </div>
  <div class="medium:col">
    <div class="form-floating">
      <select class="form-select" id="floatingSelectGrid">
        <option selected>Choose an option</option>
        <option value="1">Option One</option>
        <option value="2">Option Two</option>
        <option value="3">Option Three</option>
      </select>
      <label for="floatingSelectGrid">Preferences</label>
    </div>
  </div>
</div>

For optimal mobile experiences, consider using stacked layouts (full-width columns) on smaller screens and side-by-side layouts on larger screens using Chassis CSS's responsive column classes.

CSS

Chassis CSS uses a powerful combination of Sass and CSS variables to create a flexible form system that adapts to themes and design requirements.

This component can be customized using CSS variables, allowing for styles to be modified dynamically on the page. These CSS variables are part of Chassis CSS's design token system, giving design teams control over component appearance. See the design tokens page for more details.

Custom properties

These CSS variables control the component's appearance and can be modified dynamically on the page. Components use cascading variables, allowing seamless variations in size, color, and style without redundant style declarations through component inheritance and the context class system.

@include map-font($form-medium-text-font, input);
--#{$prefix}padding-x: var(--#{$prefix}input-padding-x, #{$form-medium-padding-x});
--#{$prefix}padding-y: var(--#{$prefix}input-padding-y, #{$form-medium-padding-y});
--#{$prefix}gap: var(--#{$prefix}input-gap, #{$form-medium-gap});
--#{$prefix}min-height: var(--#{$prefix}input-min-height, #{$form-input-min-height});
--#{$prefix}border-width: var(--#{$prefix}input-border-width, #{$form-regular-border-width});
--#{$prefix}border-radius: var(--#{$prefix}input-border-radius, #{$form-medium-border-radius});
--#{$prefix}caret-size: var(--#{$prefix}input-caret-size, #{$form-medium-caret-size});
--#{$prefix}icon-size: var(--#{$prefix}input-icon-size, #{$form-medium-icon-size});

Check the overview page to see the CSS variables shared by all form elements.

Sass variables

These Sass variables control the component's appearance and can be modified in the project's variables file before compilation.


The following variables specifically affect the appearance of floating label forms:

$form-floating-min-height:                  3.5rem;
$form-floating-line-height:                 1.25;
$form-floating-padding-x:                   $form-medium-padding-x;
$form-floating-inactive-padding-y:          1rem;
$form-floating-active-padding-t:            1.625rem;
$form-floating-active-padding-b:            .625rem;
$form-floating-label-height:                1.5em;
$form-floating-label-transform:             scale(.85) translateY(-.5rem) translateX(.15rem);
$form-floating-label-disabled-fg-color:     var(--#{$prefix}default-fg-disabled);
$form-floating-transition:                  opacity .1s ease-in-out, transform .1s ease-in-out;

Design tokens

Check the overview page to see the design tokens shared by all form elements.