Tip 31/72

How to create floating labels

Use `peer` and `placeholder-shown` to create floating labels with TailwindCSS.

<div class="group relative max-w-72 w-full">
    <input 
        type="email" 
        id="email" 
        name="email" 
        class="block peer text-gray-950 w-full px-3.5 h-12 pt-2 text-sm rounded-lg border shadow-sm shadow-gray-950/5 outline-hidden focus:ring-2 focus:ring-primary-600 dark:bg-gray-800/25 dark:border-gray-800 dark:text-white" 
        placeholder="" 
    />
    <label 
        for="email" 
        class="
            absolute block inset-y-0 my-auto left-[15px] h-fit text-sm text-nowrap text-gray-500
            -translate-y-2 pointer-events-none transition-transform duration-200 scale-[.8] origin-top-left 
            peer-focus:-translate-y-2 peer-focus:scale-[.8]  
            peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0
        "
    >
        Your Email
    </label>
</div>

Floating labels are a design pattern where a label starts inside an input field and “floats” above it when the field is focused or has a value. This technique enhances usability by maintaining the label as a visible guide without taking extra space.

Key concepts

  1. ** Input Field as the “Peer”**: Use the peer variant on the input field. This allows sibling elements (like the label) to adapt based on the state of the input.
  2. :placeholder-shown: The peer-placeholder-shown pseudo-class helps detect when the input is empty (placeholder is visible). This is used to position the label inside the field.
  3. Using peer-focus: peer-focus allows the label to respond when the input field is focused.
  4. Styling Transitions: Combine transform, scale, and translate with transition-transform to smoothly animate the label’s movement and resizing.

The Core Idea

Here’s how it works in simple terms:

  • The input field is styled with peer to share its state.
  • The label starts in a “resting” position (inside the input).
  • When the input is focused or has a value, the label “floats” up using peer-focus or peer-placeholder-shown.

Example Walkthrough

  1. Input Field:

    • The input has peer utility, so its state can control the label.
    • Place the input in a relative container for proper positioning.
  2. Label Behavior:

    • The label is absolutely positioned over the input.
    • It uses peer-placeholder-shown to stay in its original position when the input is empty.
    • When the input is focused, peer-focus shifts the label to its “floating” position.
  3. Transitions:

    • Smooth animations are achieved using utilities like transition, duration-200, translate-y, and scale.

More Examples

Label that floats above the input

<div class="group relative max-w-72 w-full">
    <div class="group relative max-w-72 w-full">
        <input 
            type="email" 
            id="email" 
            name="email" 
            class="block peer text-title w-full px-3.5 h-10 text-sm rounded-lg border outline-hidden focus:ring-2 focus:ring-primary-600 dark:bg-gray-900 dark:border-gray-800" 
            placeholder="" 
        />
        <label 
            for="email" 
            class="absolute block inset-y-0 px-2 bg-white dark:bg-gray-900 text-sm left-[7px] h-fit text-nowrap my-auto -translate-y-[19px] peer-focus:-translate-y-[19px] text-(--caption-text-color) pointer-events-none transition-transform duration-200 scale-[.8] origin-top-left peer-placeholder-shown:scale-100 peer-focus:scale-[.8] peer-placeholder-shown:translate-y-0">Your Email</label>
    </div>
</div>

Floating Label with Bottom Border Input

<div class="group relative max-w-72 w-full">
    <input 
        type="email" 
        id="email" 
        name="email" 
        class="block peer text-gray-950 w-full pb-1 text-sm border-b focus:border-primary-600 outline-hidden dark:bg-gray-900 dark:border-gray-800 dark:text-white" 
        placeholder="" 
    />
    <label 
        for="email" 
        class="
            absolute block bottom-2 left-0 text-sm h-fit text-nowrap text-gray-500
            -translate-y-4 pointer-events-none transition-transform duration-150 scale-[.8] origin-top-left 
            peer-focus:-translate-y-4 peer-focus:scale-[.8]  
            peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0
        "
    >
        Your Email
    </label>
</div>