Overview
Floating-label inputs animate the placeholder label up and out of the input box on focus or when the field has a value. The pattern uses pure CSS: :placeholder-shown + :focus-within on a wrapper drive the label transform — no JS state machine. Three variants ship: outlined notch border, bottom bar slide, and gradient halo ignite.
When to use it
Reach for floating labels on signup / login forms, settings screens, and any form where label-above-input would feel verbose. Skip them for accessibility-critical compact forms on mobile — the empty-state placeholder is hard to scan when a screen reader user is filling rapidly. Skip them for inputs that take pre-formatted content (credit card, phone); a persistent label above is more forgiving.
How it works
The wrapper element holds both the input and its <label>. The input is given a placeholder=" " (a single space) so :placeholder-shown evaluates while the input is empty — this is the “is empty” signal. The label sits absolutely positioned over the input. Two state branches: .wrap:focus-within label and .wrap input:not(:placeholder-shown) + label both apply the “floated” transform (translate up, shrink) so the label lifts on focus and stays lifted once the user has typed. The notched variant adds a clip-path or background gap to cut the border where the floated label crosses it.
Production gotchas
Browser autofill commonly skips firing the input event, leaving the field with a value but :placeholder-shown still matching for a frame — the label flickers down then back up. Listen for animationstart on a hidden -webkit-autofill keyframe to detect autofill in Chromium, or fall back to a JS check on mount. Number inputs in Safari ignore single-space placeholders; use a zero-width space or attach the “empty” signal via a wrapper class toggled on input events. Right-to-left languages need transform-origin: right on the label or the float anchor flips wrong.
Accessibility
The label must be a real <label for="..."> bound to the input’s ID — floating it visually does not change its accessible name. Screen readers announce the label normally regardless of visual position. Under prefers-reduced-motion: reduce drop the transition duration to zero so the label snaps to its floated position. Verify focus ring contrast on the input outline once the label floats out of the way.
References
Implementation depth
Animated inputs need the native label relationship first. Floating labels, notches, and underline motion should decorate a real label and input pair, not replace placeholder text as the only instruction.
Autofill and validation states are common breakpoints. Test placeholder-shown, prefilled values, error messages, and high-contrast focus so the label never overlaps typed text or disappears behind the animation.