What You'll Build

This tutorial walks you through creating a Floating Label Input Effect using only HTML and CSS. The result is a clean, modern animated form input where the placeholder label sits inside the field at rest, then smoothly floats upward and shrinks when the user focuses the input or begins typing — a staple of contemporary form UI design.

The floating label pattern improves usability and accessibility: users always know what a field is for, even after they start typing, because the label never disappears — it simply repositions itself above the input. When combined with an animated underline and CSS color transitions, the result is a polished, production-ready form component.

💡 Quick Summary: We'll use :focus and :valid pseudo-class selectors on the <input> to detect interaction state, and CSS transition with transform and font-size changes on the <label> to animate it into the floating position — no JavaScript required.

Key Features of This Floating Label Input

🏷️
Floating Label Animation
The label transitions from inside the field to above it using transform: translateY() and font-size — smooth, readable, and elegant.
🎯
:focus & :valid States
CSS :focus detects when the input is active; :valid keeps the label floating once content has been entered.
Animated Underline
A decorative underline expands from the center on focus using transform: scaleX(), adding a satisfying visual feedback cue.
🎨
Color Transitions
The label and underline smoothly shift color on focus, using CSS transition on color to reinforce the active state clearly.
Accessible by Design
Using a real <label> element linked via for and id ensures screen readers correctly associate labels with inputs.
🚀
Zero Dependencies
Pure HTML and CSS — no JavaScript, no frameworks, no build steps. Copy the files and it works instantly in any modern browser.

How It Works — Step by Step

Here's a breakdown of the two core layers that power this floating label input effect.

01

HTML Structure

The markup wraps each input and its label inside a shared container element — typically a <div class="form-group">. Inside, the <input> comes before the <label> in the source order. This ordering is intentional: it allows the CSS adjacent sibling combinator (input + label or input ~ label) to target the label based on the input's state, which is the entire mechanism behind the CSS-only floating effect. The required attribute on the input is also important — it enables the :valid selector to fire correctly once the field has content.

02

CSS — Label Float & Underline Animation

All the interaction lives in CSS. By default, the <label> is absolutely positioned inside the form group, sitting at the baseline of the input field to mimic a placeholder. When the input receives :focus, or when it becomes :valid (meaning the user has typed something), the adjacent label is targeted with a sibling selector: input:focus ~ label, input:valid ~ label. At this point, CSS applies transform: translateY(-1.4rem) and a smaller font-size to animate the label upward into the floating position. Simultaneously, an animated underline — a ::after pseudo-element with transform: scaleX(0) at rest — expands to scaleX(1) on focus, growing from the center outward to complete the polished effect. A transition property on both elements ensures all changes animate smoothly at a comfortable speed.

⚠️ Important: Input Order Matters. The <input> element must appear before the <label> in the HTML. CSS can only select elements that come after a target in the source — there is no "previous sibling" selector in CSS. If the label is placed first, the :focus ~ label technique will not work. Use position: absolute on the label to visually layer it over the input regardless of DOM order.

Understanding :focus and :valid

The :focus pseudo-class matches an input element exactly while it has keyboard focus — the moment the user clicks or tabs into the field. The :valid pseudo-class matches when the input's value satisfies its constraints (for a required text input, this means the field is not empty). Together they cover both active typing and the state after the user moves on, ensuring the label stays floating so it never obscures filled-in content.

The Animated Underline

The underline decoration is built using a CSS ::after pseudo-element on the form group container. At rest, it has width: 100% but transform: scaleX(0), making it invisible. On focus, it transitions to scaleX(1) with transform-origin: center, so it expands outward from the middle of the field — a widely recognized UX pattern from Material Design that users immediately associate with an active, interactive input field.


Get the Source Code

The full source code is available for free. Scroll down and wait for the countdown to finish to get the GitHub Gist link. Or explore the code preview below.

HTML — index.html
CSS — style.css
/* Loading source code... */
💡 Quick Start: Copy both files into the same folder and open index.html in your browser. No server or build tool required — the floating label effect renders instantly. Make sure to include the required attribute on your inputs so the :valid selector fires correctly once the field has content.

Full source code available after countdown

10 seconds...

Frequently Asked Questions

What is a floating label and why use it?
A floating label is a form input pattern where the label starts inside the field — looking like a placeholder — and then animates upward when the user focuses or fills in the input. Unlike a plain HTML placeholder, the label never disappears once typing starts, so users always know what information a field is asking for. This improves both usability and accessibility, especially on long forms where context is easy to lose.
How does the label animate without JavaScript?
The animation is handled entirely by CSS. The <label> is absolutely positioned inside a relative container so it overlays the input visually. When the input receives :focus or becomes :valid, a CSS sibling selector (input:focus ~ label) targets the label and applies transform: translateY() and a smaller font-size. A transition on the label smooths the position and size change over time — producing the floating animation with zero JavaScript.
Why does the input need to come before the label in HTML?
CSS sibling selectors like ~ (general sibling) only work forward in the DOM — they can select elements that appear after the reference element, never before. Since we need to select the label based on the input's state (:focus, :valid), the <input> must come first in the HTML source. Absolute positioning on the label then lets us layer it visually over the input regardless of source order.
Can I customize the colors and animation speed?
Yes — all colors, transition durations, and spacing values are defined with CSS custom properties (variables), making customization straightforward. Change --label-color for the default label color, --focus-color for the active state accent, and adjust the transition duration on the label and underline to speed up or slow down the animation. Swap the underline color to match any brand palette instantly.
Is this accessible for screen reader users?
Yes. Because the pattern uses a real <label> element connected to the input via matching for and id attributes, screen readers correctly announce the label when the input receives focus — the same behavior as any standard form. Unlike styling a placeholder alone (which disappears on input and has poor contrast support), this approach fully meets accessibility expectations for labelled form controls.

Conclusion

The Floating Label Input Effect demonstrates just how expressive modern CSS has become. By combining CSS sibling selectors with the :focus and :valid pseudo-classes, smooth transition animations, and a scaleX underline effect, you get a production-ready, accessible animated form component with absolutely zero JavaScript and zero external dependencies.

This technique is highly versatile: use it for login forms, registration pages, contact forms, checkout flows, or any UI where clean, modern input design matters. Adjust the label color, underline accent, animation timing, and typography to match your design language in minutes — all through CSS custom properties.

Found this useful? Explore more HTML & CSS projects in the sidebar →