27 / 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 Password Toggle Input
An eye button that swaps type="password" for type="text", with the icon swap driven entirely by aria-pressed. Role, name and state change in lockstep — WCAG 4.1.2 satisfied by construction rather than by discipline.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<div class="tif-27 grid min-h-svh w-full place-items-center bg-tif27-bg px-6 py-14 font-tif27-sans" aria-label="Password toggle input demo">
<label class="grid w-full max-w-70 gap-1.5">
<span class="font-tif27-mono text-[10px] tracking-[0.12em] text-tif27-mut uppercase">Password</span>
<span class="flex items-center rounded-[10px] border border-white/12 bg-tif27-field py-0.5 pr-1 pl-3.5 transition-colors duration-200 focus-within:border-tif27-acc">
<input type="password" name="tif27-pw" autocomplete="new-password" placeholder="At least 8 characters" minlength="8" data-tif27-input
class="min-w-0 flex-1 border-0 bg-transparent py-3 text-sm font-medium tracking-[0.08em] text-tif27-ink outline-none placeholder:tracking-normal placeholder:text-tif27-mut">
<button type="button" aria-label="Show password" aria-pressed="false" data-tif27-toggle
class="group grid size-11 shrink-0 cursor-pointer place-items-center rounded-md border-0 bg-transparent transition-colors duration-150 hover:bg-white/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tif27-acc">
<svg viewBox="0 0 24 24" aria-hidden="true" class="size-4 fill-none stroke-tif27-mut stroke-2 [stroke-linecap:round] [stroke-linejoin:round] group-aria-pressed:hidden group-aria-pressed:stroke-tif27-acc"><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
<svg viewBox="0 0 24 24" aria-hidden="true" class="hidden size-4 fill-none stroke-tif27-acc stroke-2 [stroke-linecap:round] [stroke-linejoin:round] group-aria-pressed:block"><path d="M3 3l18 18M9.9 5.1A10 10 0 0 1 22 12a16 16 0 0 1-2.7 3.7M6.7 6.7A16 16 0 0 0 2 12s4 7 10 7a10 10 0 0 0 4.1-.9"/></svg>
</button>
</span>
</label>
</div><div class="tif-27 grid min-h-svh w-full place-items-center bg-tif27-bg px-6 py-14 font-tif27-sans" aria-label="Password toggle input demo">
<label class="grid w-full max-w-70 gap-1.5">
<span class="font-tif27-mono text-[10px] tracking-[0.12em] text-tif27-mut uppercase">Password</span>
<span class="flex items-center rounded-[10px] border border-white/12 bg-tif27-field py-0.5 pr-1 pl-3.5 transition-colors duration-200 focus-within:border-tif27-acc">
<input type="password" name="tif27-pw" autocomplete="new-password" placeholder="At least 8 characters" minlength="8" data-tif27-input
class="min-w-0 flex-1 border-0 bg-transparent py-3 text-sm font-medium tracking-[0.08em] text-tif27-ink outline-none placeholder:tracking-normal placeholder:text-tif27-mut">
<button type="button" aria-label="Show password" aria-pressed="false" data-tif27-toggle
class="group grid size-11 shrink-0 cursor-pointer place-items-center rounded-md border-0 bg-transparent transition-colors duration-150 hover:bg-white/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tif27-acc">
<svg viewBox="0 0 24 24" aria-hidden="true" class="size-4 fill-none stroke-tif27-mut stroke-2 [stroke-linecap:round] [stroke-linejoin:round] group-aria-pressed:hidden group-aria-pressed:stroke-tif27-acc"><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
<svg viewBox="0 0 24 24" aria-hidden="true" class="hidden size-4 fill-none stroke-tif27-acc stroke-2 [stroke-linecap:round] [stroke-linejoin:round] group-aria-pressed:block"><path d="M3 3l18 18M9.9 5.1A10 10 0 0 1 22 12a16 16 0 0 1-2.7 3.7M6.7 6.7A16 16 0 0 0 2 12s4 7 10 7a10 10 0 0 0 4.1-.9"/></svg>
</button>
</span>
</label>
</div>@import "tailwindcss";
@theme {
--color-tif27-bg: #12121a;
--color-tif27-bg: oklch(0.19 0.015 285);
--color-tif27-field: #1a1a22;
--color-tif27-field: oklch(0.23 0.015 285);
--color-tif27-ink: #f0eeff;
--color-tif27-ink: oklch(0.95 0.02 290);
--color-tif27-mut: #b8b6d4;
--color-tif27-mut: oklch(0.77 0.03 290);
--color-tif27-acc: #7c6cff;
--color-tif27-acc: oklch(0.62 0.2 288);
--font-tif27-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tif27-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tif-27 {
width: 100%;
}
.tif-27 ::selection {
background: var(--color-tif27-acc);
color: #12121a;
}@import "tailwindcss";
@theme {
--color-tif27-bg: #12121a;
--color-tif27-bg: oklch(0.19 0.015 285);
--color-tif27-field: #1a1a22;
--color-tif27-field: oklch(0.23 0.015 285);
--color-tif27-ink: #f0eeff;
--color-tif27-ink: oklch(0.95 0.02 290);
--color-tif27-mut: #b8b6d4;
--color-tif27-mut: oklch(0.77 0.03 290);
--color-tif27-acc: #7c6cff;
--color-tif27-acc: oklch(0.62 0.2 288);
--font-tif27-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tif27-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tif-27 {
width: 100%;
}
.tif-27 ::selection {
background: var(--color-tif27-acc);
color: #12121a;
}(function () {
document.querySelectorAll('.tif-27').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var input = root.querySelector('[data-tif27-input]');
var btn = root.querySelector('[data-tif27-toggle]');
if (!input || !btn) return;
btn.addEventListener('click', function () {
var on = btn.getAttribute('aria-pressed') === 'true';
btn.setAttribute('aria-pressed', on ? 'false' : 'true');
btn.setAttribute('aria-label', on ? 'Show password' : 'Hide password');
input.type = on ? 'password' : 'text';
});
});
})();(function () {
document.querySelectorAll('.tif-27').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var input = root.querySelector('[data-tif27-input]');
var btn = root.querySelector('[data-tif27-toggle]');
if (!input || !btn) return;
btn.addEventListener('click', function () {
var on = btn.getAttribute('aria-pressed') === 'true';
btn.setAttribute('aria-pressed', on ? 'false' : 'true');
btn.setAttribute('aria-label', on ? 'Show password' : 'Hide password');
input.type = on ? 'password' : 'text';
});
});
})();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-tif27-bg: #12121a;
--color-tif27-bg: oklch(0.19 0.015 285);
--color-tif27-field: #1a1a22;
--color-tif27-field: oklch(0.23 0.015 285);
--color-tif27-ink: #f0eeff;
--color-tif27-ink: oklch(0.95 0.02 290);
--color-tif27-mut: #b8b6d4;
--color-tif27-mut: oklch(0.77 0.03 290);
--color-tif27-acc: #7c6cff;
--color-tif27-acc: oklch(0.62 0.2 288);
--font-tif27-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tif27-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tif-27 {
width: 100%;
}
.tif-27 ::selection {
background: var(--color-tif27-acc);
color: #12121a;
}@import "tailwindcss";
@theme {
--color-tif27-bg: #12121a;
--color-tif27-bg: oklch(0.19 0.015 285);
--color-tif27-field: #1a1a22;
--color-tif27-field: oklch(0.23 0.015 285);
--color-tif27-ink: #f0eeff;
--color-tif27-ink: oklch(0.95 0.02 290);
--color-tif27-mut: #b8b6d4;
--color-tif27-mut: oklch(0.77 0.03 290);
--color-tif27-acc: #7c6cff;
--color-tif27-acc: oklch(0.62 0.2 288);
--font-tif27-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tif27-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tif-27 {
width: 100%;
}
.tif-27 ::selection {
background: var(--color-tif27-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=JetBrains+Mono:wght@400;500;700&family=Plus+Jakarta+Sans:wght@400;500;600&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=JetBrains+Mono:wght@400;500;700&family=Plus+Jakarta+Sans:wght@400;500;600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Bug fixed. The CSS original's demo 27 stylesheet contains a whole strength-meter sheet redefining
.if-27and.if-27 inputbefore the toggle styles, with markup that is not in the demo. This entry is the toggle alone; the meter is entry 09. - The two
[aria-pressed="true"] .iconrules becomegroup-aria-pressed:hidden/:blockon the icons themselves. - The button grew 32px →
size-11and gained a focus-visible ring.
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 Password Toggle Input
Source: https://codefronts.com/components/tailwind-css-input-fields/tailwind-password-toggle-input/
An eye button that swaps type="password" for type="text", with the icon swap driven entirely by aria-pressed. Role, name and state change in lockstep — WCAG 4.1.2 satisfied by construction rather than by discipline.
## HTML
```html
<div class="tif-27 grid min-h-svh w-full place-items-center bg-tif27-bg px-6 py-14 font-tif27-sans" aria-label="Password toggle input demo">
<label class="grid w-full max-w-70 gap-1.5">
<span class="font-tif27-mono text-[10px] tracking-[0.12em] text-tif27-mut uppercase">Password</span>
<span class="flex items-center rounded-[10px] border border-white/12 bg-tif27-field py-0.5 pr-1 pl-3.5 transition-colors duration-200 focus-within:border-tif27-acc">
<input type="password" name="tif27-pw" autocomplete="new-password" placeholder="At least 8 characters" minlength="8" data-tif27-input
class="min-w-0 flex-1 border-0 bg-transparent py-3 text-sm font-medium tracking-[0.08em] text-tif27-ink outline-none placeholder:tracking-normal placeholder:text-tif27-mut">
<button type="button" aria-label="Show password" aria-pressed="false" data-tif27-toggle
class="group grid size-11 shrink-0 cursor-pointer place-items-center rounded-md border-0 bg-transparent transition-colors duration-150 hover:bg-white/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tif27-acc">
<svg viewBox="0 0 24 24" aria-hidden="true" class="size-4 fill-none stroke-tif27-mut stroke-2 [stroke-linecap:round] [stroke-linejoin:round] group-aria-pressed:hidden group-aria-pressed:stroke-tif27-acc"><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
<svg viewBox="0 0 24 24" aria-hidden="true" class="hidden size-4 fill-none stroke-tif27-acc stroke-2 [stroke-linecap:round] [stroke-linejoin:round] group-aria-pressed:block"><path d="M3 3l18 18M9.9 5.1A10 10 0 0 1 22 12a16 16 0 0 1-2.7 3.7M6.7 6.7A16 16 0 0 0 2 12s4 7 10 7a10 10 0 0 0 4.1-.9"/></svg>
</button>
</span>
</label>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tif27-bg: #12121a;
--color-tif27-bg: oklch(0.19 0.015 285);
--color-tif27-field: #1a1a22;
--color-tif27-field: oklch(0.23 0.015 285);
--color-tif27-ink: #f0eeff;
--color-tif27-ink: oklch(0.95 0.02 290);
--color-tif27-mut: #b8b6d4;
--color-tif27-mut: oklch(0.77 0.03 290);
--color-tif27-acc: #7c6cff;
--color-tif27-acc: oklch(0.62 0.2 288);
--font-tif27-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tif27-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tif-27 {
width: 100%;
}
.tif-27 ::selection {
background: var(--color-tif27-acc);
color: #12121a;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tif-27').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var input = root.querySelector('[data-tif27-input]');
var btn = root.querySelector('[data-tif27-toggle]');
if (!input || !btn) return;
btn.addEventListener('click', function () {
var on = btn.getAttribute('aria-pressed') === 'true';
btn.setAttribute('aria-pressed', on ? 'false' : 'true');
btn.setAttribute('aria-label', on ? 'Show password' : 'Hide password');
input.type = on ? 'password' : 'text';
});
});
})();
```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 Password Toggle Input
Source: https://codefronts.com/components/tailwind-css-input-fields/tailwind-password-toggle-input/
An eye button that swaps type="password" for type="text", with the icon swap driven entirely by aria-pressed. Role, name and state change in lockstep — WCAG 4.1.2 satisfied by construction rather than by discipline.
## HTML
```html
<div class="tif-27 grid min-h-svh w-full place-items-center bg-tif27-bg px-6 py-14 font-tif27-sans" aria-label="Password toggle input demo">
<label class="grid w-full max-w-70 gap-1.5">
<span class="font-tif27-mono text-[10px] tracking-[0.12em] text-tif27-mut uppercase">Password</span>
<span class="flex items-center rounded-[10px] border border-white/12 bg-tif27-field py-0.5 pr-1 pl-3.5 transition-colors duration-200 focus-within:border-tif27-acc">
<input type="password" name="tif27-pw" autocomplete="new-password" placeholder="At least 8 characters" minlength="8" data-tif27-input
class="min-w-0 flex-1 border-0 bg-transparent py-3 text-sm font-medium tracking-[0.08em] text-tif27-ink outline-none placeholder:tracking-normal placeholder:text-tif27-mut">
<button type="button" aria-label="Show password" aria-pressed="false" data-tif27-toggle
class="group grid size-11 shrink-0 cursor-pointer place-items-center rounded-md border-0 bg-transparent transition-colors duration-150 hover:bg-white/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tif27-acc">
<svg viewBox="0 0 24 24" aria-hidden="true" class="size-4 fill-none stroke-tif27-mut stroke-2 [stroke-linecap:round] [stroke-linejoin:round] group-aria-pressed:hidden group-aria-pressed:stroke-tif27-acc"><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
<svg viewBox="0 0 24 24" aria-hidden="true" class="hidden size-4 fill-none stroke-tif27-acc stroke-2 [stroke-linecap:round] [stroke-linejoin:round] group-aria-pressed:block"><path d="M3 3l18 18M9.9 5.1A10 10 0 0 1 22 12a16 16 0 0 1-2.7 3.7M6.7 6.7A16 16 0 0 0 2 12s4 7 10 7a10 10 0 0 0 4.1-.9"/></svg>
</button>
</span>
</label>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tif27-bg: #12121a;
--color-tif27-bg: oklch(0.19 0.015 285);
--color-tif27-field: #1a1a22;
--color-tif27-field: oklch(0.23 0.015 285);
--color-tif27-ink: #f0eeff;
--color-tif27-ink: oklch(0.95 0.02 290);
--color-tif27-mut: #b8b6d4;
--color-tif27-mut: oklch(0.77 0.03 290);
--color-tif27-acc: #7c6cff;
--color-tif27-acc: oklch(0.62 0.2 288);
--font-tif27-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tif27-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tif-27 {
width: 100%;
}
.tif-27 ::selection {
background: var(--color-tif27-acc);
color: #12121a;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tif-27').forEach(function (root) {
if (root.dataset.bound) return; root.dataset.bound = '1';
var input = root.querySelector('[data-tif27-input]');
var btn = root.querySelector('[data-tif27-toggle]');
if (!input || !btn) return;
btn.addEventListener('click', function () {
var on = btn.getAttribute('aria-pressed') === 'true';
btn.setAttribute('aria-pressed', on ? 'false' : 'true');
btn.setAttribute('aria-label', on ? 'Show password' : 'Hide password');
input.type = on ? 'password' : 'text';
});
});
})();
```How this works
One attribute, three consequences. The click handler changes state and name; CSS changes appearance:
btn.setAttribute('aria-pressed', on ? 'false' : 'true');
btn.setAttribute('aria-label', on ? 'Show password' : 'Hide password');
input.type = on ? 'password' : 'text';Why not a checkbox. A toggle button that reveals content is a button with aria-pressed, not a checkbox with aria-checked — aria-checked belongs to checkbox, radio and menuitemcheckbox roles, and using it here makes a screen reader describe the wrong widget.
Make it yours
- Icons: any pair, kept
aria-hiddenso the button's label is the sole announcement. - Sign-in flows:
autocomplete="current-password"instead ofnew-password. - Voice: rename the two labels (Reveal / Hide) in the handler.
- Strength meter: pair with demo 09 — they were one tangled stylesheet in the CSS original and are two clean demos here.
Gotchas — read before shipping
aria-pressed, neveraria-checked.- Never let the icon and the input type fall out of sync, even for a frame — stale state is worse than no state.
- Some password managers stop autofilling once
typeistext. Keep theautocompletehint intact so they recover.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
aria-pressed and the type property swap are universal; the floor is Tailwind v4's generated sheet.