Vanilla Breeze

data-floating-label

Animated floating label that starts inside the input and moves above on focus or when filled. Material Design pattern that keeps the label always visible.

Overview

The data-floating-label attribute upscales the static <label> into an animated floating label. The label starts inside the input (like a placeholder) and smoothly animates above the border when the field gains focus or has a value. Unlike a placeholder, the label never disappears — the user always knows what the field is for.

How It Works

  1. JS init — Adds a transparent placeholder=" " to the input (if missing) so the CSS :placeholder-shown selector activates correctly. Marks the field as data-floating-label-ready.
  2. CSS drives the animation — The label is positioned absolutely over the input. Two CSS selectors handle the transition:
    • :focus-within — user focuses the field
    • :not(:placeholder-shown) — field has a value
  3. Label floats up — transforms to a smaller size above the input border with a background to punch through the border line.

Attributes

Attribute On Description
data-floating-label <form-field> Enable floating label animation on this field.

Input Types

Works with all standard text-like inputs, textareas, and selects:

Select elements float the label immediately since they always have a value.

With Validation

Floating labels work alongside <form-field> validation. Required indicators, error messages, and valid states all function normally:

Accessibility

  • The <label> remains a real label with for binding — screen readers always announce it.
  • The label uses pointer-events: none so clicking the label area focuses the input.
  • The animation respects prefers-reduced-motion — transitions are disabled.
  • The label never disappears (unlike placeholder), maintaining context at all times.

Comparison

Pattern Label visible when typing? Compact layout?
Standard label Yes (always above) No (takes vertical space)
Placeholder only No (vanishes) Yes
Floating label Yes (floats up) Yes (compact when empty)