01 / 28
All 28 in 28 Tailwind CSS Input Fields
- 01Tailwind Floating Label Input
- 02Tailwind Underline Sweep Input
- 03Tailwind Neon Glow Input
- 04Tailwind Frosted Glass Input
- 05Tailwind Notched Outline Input
- 06Tailwind Drawn Border Input
- 07Tailwind Inline Validation Input
- 08Tailwind Search Input With Clear
- 09Tailwind Password Strength Meter
- 10Tailwind OTP Code Input
- 11Tailwind Rotating Placeholder Input
- 12Tailwind Tag Chip Input
- 13Tailwind Phone Input With Country
- 14Tailwind Stepper Number Input
- 15Tailwind File Drop Zone
- 16Tailwind Currency Input
- 17Tailwind Native Date Input
- 18Tailwind Time Range Input
- 19Tailwind Colour Picker Input
- 20Tailwind Voice Search Input
- 21Tailwind Email Suggestion Combobox
- 22Tailwind Auto-Grow Textarea
- 23Tailwind Inline Edit Field
- 24Tailwind Range Slider
- 25Tailwind URL Input With Protocol
- 26Tailwind Credit Card Input
- 27Tailwind Password Toggle Input
- 28Tailwind Brutalist Input
Tailwind Floating Label Input
The canonical floating label, and the demo that teaches the whole collection: peer on the input, peer-focus: and peer-[:not(:placeholder-shown)]: on the label. The CSS original writes two selector blocks that live nowhere near the label; here the label owns both of its lifted states.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<div class="tif-01 grid min-h-svh w-full place-items-center bg-tif01-bg px-6 py-14 font-tif01-sans" aria-label="Floating label input demo">
<label class="relative block w-full max-w-70">
<input type="email" name="tif01-email" autocomplete="email" placeholder=" " required
class="peer w-full rounded-xl border border-white/12 bg-tif01-field px-3.5 pt-4.5 pb-2 text-sm text-tif01-ink outline-none transition-[border-color,background-color] duration-200 focus:border-tif01-acc2 focus:bg-tif01-field2">
<span class="pointer-events-none absolute top-3.5 left-3.5 text-[13px] tracking-normal text-tif01-mut transition-[transform,font-size,color,letter-spacing] duration-200 peer-focus:-translate-y-2.5 peer-focus:text-[10px] peer-focus:tracking-[0.06em] peer-focus:text-tif01-acc peer-focus:uppercase peer-[:not(:placeholder-shown)]:-translate-y-2.5 peer-[:not(:placeholder-shown)]:text-[10px] peer-[:not(:placeholder-shown)]:tracking-[0.06em] peer-[:not(:placeholder-shown)]:text-tif01-acc peer-[:not(:placeholder-shown)]:uppercase motion-reduce:transition-none">Email address</span>
</label>
</div><div class="tif-01 grid min-h-svh w-full place-items-center bg-tif01-bg px-6 py-14 font-tif01-sans" aria-label="Floating label input demo">
<label class="relative block w-full max-w-70">
<input type="email" name="tif01-email" autocomplete="email" placeholder=" " required
class="peer w-full rounded-xl border border-white/12 bg-tif01-field px-3.5 pt-4.5 pb-2 text-sm text-tif01-ink outline-none transition-[border-color,background-color] duration-200 focus:border-tif01-acc2 focus:bg-tif01-field2">
<span class="pointer-events-none absolute top-3.5 left-3.5 text-[13px] tracking-normal text-tif01-mut transition-[transform,font-size,color,letter-spacing] duration-200 peer-focus:-translate-y-2.5 peer-focus:text-[10px] peer-focus:tracking-[0.06em] peer-focus:text-tif01-acc peer-focus:uppercase peer-[:not(:placeholder-shown)]:-translate-y-2.5 peer-[:not(:placeholder-shown)]:text-[10px] peer-[:not(:placeholder-shown)]:tracking-[0.06em] peer-[:not(:placeholder-shown)]:text-tif01-acc peer-[:not(:placeholder-shown)]:uppercase motion-reduce:transition-none">Email address</span>
</label>
</div>@import "tailwindcss";
@theme {
--color-tif01-bg: #12121a;
--color-tif01-bg: oklch(0.19 0.015 285);
--color-tif01-field: #1a1a22;
--color-tif01-field: oklch(0.23 0.015 285);
--color-tif01-field2: #1f1f2a;
--color-tif01-field2: oklch(0.26 0.018 285);
--color-tif01-ink: #f0eeff;
--color-tif01-ink: oklch(0.95 0.02 290);
--color-tif01-mut: #b8b6d4;
--color-tif01-mut: oklch(0.77 0.03 290);
--color-tif01-acc: #a78bfa;
--color-tif01-acc: oklch(0.74 0.15 295);
--color-tif01-acc2: #7c6cff;
--color-tif01-acc2: oklch(0.62 0.2 288);
--font-tif01-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* Stage contract, stated in CSS as well as in the markup, so the demo is sized
before the browser build compiles. */
.tif-01 {
width: 100%;
}
.tif-01 ::selection {
background: var(--color-tif01-acc);
color: #12121a;
}@import "tailwindcss";
@theme {
--color-tif01-bg: #12121a;
--color-tif01-bg: oklch(0.19 0.015 285);
--color-tif01-field: #1a1a22;
--color-tif01-field: oklch(0.23 0.015 285);
--color-tif01-field2: #1f1f2a;
--color-tif01-field2: oklch(0.26 0.018 285);
--color-tif01-ink: #f0eeff;
--color-tif01-ink: oklch(0.95 0.02 290);
--color-tif01-mut: #b8b6d4;
--color-tif01-mut: oklch(0.77 0.03 290);
--color-tif01-acc: #a78bfa;
--color-tif01-acc: oklch(0.74 0.15 295);
--color-tif01-acc2: #7c6cff;
--color-tif01-acc2: oklch(0.62 0.2 288);
--font-tif01-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* Stage contract, stated in CSS as well as in the markup, so the demo is sized
before the browser build compiles. */
.tif-01 {
width: 100%;
}
.tif-01 ::selection {
background: var(--color-tif01-acc);
color: #12121a;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tif01-bg: #12121a;
--color-tif01-bg: oklch(0.19 0.015 285);
--color-tif01-field: #1a1a22;
--color-tif01-field: oklch(0.23 0.015 285);
--color-tif01-field2: #1f1f2a;
--color-tif01-field2: oklch(0.26 0.018 285);
--color-tif01-ink: #f0eeff;
--color-tif01-ink: oklch(0.95 0.02 290);
--color-tif01-mut: #b8b6d4;
--color-tif01-mut: oklch(0.77 0.03 290);
--color-tif01-acc: #a78bfa;
--color-tif01-acc: oklch(0.74 0.15 295);
--color-tif01-acc2: #7c6cff;
--color-tif01-acc2: oklch(0.62 0.2 288);
--font-tif01-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* Stage contract, stated in CSS as well as in the markup, so the demo is sized
before the browser build compiles. */
.tif-01 {
width: 100%;
}
.tif-01 ::selection {
background: var(--color-tif01-acc);
color: #12121a;
}@import "tailwindcss";
@theme {
--color-tif01-bg: #12121a;
--color-tif01-bg: oklch(0.19 0.015 285);
--color-tif01-field: #1a1a22;
--color-tif01-field: oklch(0.23 0.015 285);
--color-tif01-field2: #1f1f2a;
--color-tif01-field2: oklch(0.26 0.018 285);
--color-tif01-ink: #f0eeff;
--color-tif01-ink: oklch(0.95 0.02 290);
--color-tif01-mut: #b8b6d4;
--color-tif01-mut: oklch(0.77 0.03 290);
--color-tif01-acc: #a78bfa;
--color-tif01-acc: oklch(0.74 0.15 295);
--color-tif01-acc2: #7c6cff;
--color-tif01-acc2: oklch(0.62 0.2 288);
--font-tif01-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* Stage contract, stated in CSS as well as in the markup, so the demo is sized
before the browser build compiles. */
.tif-01 {
width: 100%;
}
.tif-01 ::selection {
background: var(--color-tif01-acc);
color: #12121a;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Two selector blocks (
input:focus + .labelandinput:not(:placeholder-shown) + .label) collapse into one class list on the label itself. - The three separate
transitiondeclarations become onetransition-[…]per element, so they cannot drift out of lockstep. @media (prefers-reduced-motion)was absent from the original; it is one utility here, so there is no excuse.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Floating Label Input
Source: https://codefronts.com/components/tailwind-css-input-fields/tailwind-floating-label-input/
The canonical floating label, and the demo that teaches the whole collection: peer on the input, peer-focus: and peer-[:not(:placeholder-shown)]: on the label. The CSS original writes two selector blocks that live nowhere near the label; here the label owns both of its lifted states.
## HTML
```html
<div class="tif-01 grid min-h-svh w-full place-items-center bg-tif01-bg px-6 py-14 font-tif01-sans" aria-label="Floating label input demo">
<label class="relative block w-full max-w-70">
<input type="email" name="tif01-email" autocomplete="email" placeholder=" " required
class="peer w-full rounded-xl border border-white/12 bg-tif01-field px-3.5 pt-4.5 pb-2 text-sm text-tif01-ink outline-none transition-[border-color,background-color] duration-200 focus:border-tif01-acc2 focus:bg-tif01-field2">
<span class="pointer-events-none absolute top-3.5 left-3.5 text-[13px] tracking-normal text-tif01-mut transition-[transform,font-size,color,letter-spacing] duration-200 peer-focus:-translate-y-2.5 peer-focus:text-[10px] peer-focus:tracking-[0.06em] peer-focus:text-tif01-acc peer-focus:uppercase peer-[:not(:placeholder-shown)]:-translate-y-2.5 peer-[:not(:placeholder-shown)]:text-[10px] peer-[:not(:placeholder-shown)]:tracking-[0.06em] peer-[:not(:placeholder-shown)]:text-tif01-acc peer-[:not(:placeholder-shown)]:uppercase motion-reduce:transition-none">Email address</span>
</label>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tif01-bg: #12121a;
--color-tif01-bg: oklch(0.19 0.015 285);
--color-tif01-field: #1a1a22;
--color-tif01-field: oklch(0.23 0.015 285);
--color-tif01-field2: #1f1f2a;
--color-tif01-field2: oklch(0.26 0.018 285);
--color-tif01-ink: #f0eeff;
--color-tif01-ink: oklch(0.95 0.02 290);
--color-tif01-mut: #b8b6d4;
--color-tif01-mut: oklch(0.77 0.03 290);
--color-tif01-acc: #a78bfa;
--color-tif01-acc: oklch(0.74 0.15 295);
--color-tif01-acc2: #7c6cff;
--color-tif01-acc2: oklch(0.62 0.2 288);
--font-tif01-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* Stage contract, stated in CSS as well as in the markup, so the demo is sized
before the browser build compiles. */
.tif-01 {
width: 100%;
}
.tif-01 ::selection {
background: var(--color-tif01-acc);
color: #12121a;
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Floating Label Input
Source: https://codefronts.com/components/tailwind-css-input-fields/tailwind-floating-label-input/
The canonical floating label, and the demo that teaches the whole collection: peer on the input, peer-focus: and peer-[:not(:placeholder-shown)]: on the label. The CSS original writes two selector blocks that live nowhere near the label; here the label owns both of its lifted states.
## HTML
```html
<div class="tif-01 grid min-h-svh w-full place-items-center bg-tif01-bg px-6 py-14 font-tif01-sans" aria-label="Floating label input demo">
<label class="relative block w-full max-w-70">
<input type="email" name="tif01-email" autocomplete="email" placeholder=" " required
class="peer w-full rounded-xl border border-white/12 bg-tif01-field px-3.5 pt-4.5 pb-2 text-sm text-tif01-ink outline-none transition-[border-color,background-color] duration-200 focus:border-tif01-acc2 focus:bg-tif01-field2">
<span class="pointer-events-none absolute top-3.5 left-3.5 text-[13px] tracking-normal text-tif01-mut transition-[transform,font-size,color,letter-spacing] duration-200 peer-focus:-translate-y-2.5 peer-focus:text-[10px] peer-focus:tracking-[0.06em] peer-focus:text-tif01-acc peer-focus:uppercase peer-[:not(:placeholder-shown)]:-translate-y-2.5 peer-[:not(:placeholder-shown)]:text-[10px] peer-[:not(:placeholder-shown)]:tracking-[0.06em] peer-[:not(:placeholder-shown)]:text-tif01-acc peer-[:not(:placeholder-shown)]:uppercase motion-reduce:transition-none">Email address</span>
</label>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tif01-bg: #12121a;
--color-tif01-bg: oklch(0.19 0.015 285);
--color-tif01-field: #1a1a22;
--color-tif01-field: oklch(0.23 0.015 285);
--color-tif01-field2: #1f1f2a;
--color-tif01-field2: oklch(0.26 0.018 285);
--color-tif01-ink: #f0eeff;
--color-tif01-ink: oklch(0.95 0.02 290);
--color-tif01-mut: #b8b6d4;
--color-tif01-mut: oklch(0.77 0.03 290);
--color-tif01-acc: #a78bfa;
--color-tif01-acc: oklch(0.74 0.15 295);
--color-tif01-acc2: #7c6cff;
--color-tif01-acc2: oklch(0.62 0.2 288);
--font-tif01-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}
/* Stage contract, stated in CSS as well as in the markup, so the demo is sized
before the browser build compiles. */
.tif-01 {
width: 100%;
}
.tif-01 ::selection {
background: var(--color-tif01-acc);
color: #12121a;
}
```How this works
The label states its own lifted geometry. Both triggers — focused and filled — resolve to the same four utilities, written once on the element that moves:
class="absolute top-3.5 left-3.5 text-[13px]
peer-focus:-translate-y-2.5 peer-focus:text-[10px]
peer-[:not(:placeholder-shown)]:-translate-y-2.5 …"The peer must precede the label in the DOM, because peer-* compiles to a general-sibling selector. That is the same constraint the CSS version has with +, but stated on the element rather than in a stylesheet — reorder the markup and the class simply stops applying, in view, where you can see it.
Make it yours
- Accent:
--color-tif01-acc(lifted label) and--color-tif01-acc2(focus border) in@theme— they work as a light/dark pair. - Lift distance:
-translate-y-2.5, paired with the input'spt-4.5 pb-2so text never collides with the label. - Motion: one
duration-200on the input and one on the label. Keep them equal. - Sentence case: drop
peer-focus:uppercaseand bumptext-[10px]totext-[11px].
Gotchas — read before shipping
- The
placeholdermust be a single space. Remove it and:placeholder-shownnever matches, so the label sits lifted forever. peer-*is a sibling selector: the label must come after the input and share a parent. Wrapping either kills the lift silently.- Chrome autofill does not always re-evaluate
:placeholder-shown— test with a saved credential before shipping a login form.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
:placeholder-shown is Baseline; the floor quoted is Tailwind v4's generated sheet.