12 / 30
All 30 in 30 Tailwind CSS Login Forms
- 01Tailwind Split-Screen Brand Hero Login Form
- 02Tailwind Multi-Tenant Workspace Account Switcher
- 03Tailwind Floating Label Login Form with peer Variants
- 04Tailwind Web3 Wallet Connect Login Grid
- 05Tailwind Minimalist Fintech Login Card with Layered Shadow
- 06Tailwind OAuth Social Login Form with Brand SVG Buttons
- 07Tailwind Passwordless Magic Link Login with data-state Machine
- 08Tailwind Aurora Glow Login Card with Drifting Blur Blobs
- 09Tailwind Neon Synthwave Arcade Login Form
- 10Tailwind Sliding Login and Sign Up Panel with peer-checked
- 11Tailwind 3D Flip Login Card with Password Reset Back Face
- 12Tailwind Terminal CLI Prompt Login Form
- 13Tailwind Floating Pill Login Widget Docked Over App Content
- 14Tailwind Gradient Border Login Card with background-clip
- 15Tailwind Slide-Over Side Panel Login without JavaScript
- 16Tailwind Social-First Sign Up with Brand-Compliant Buttons
- 17Tailwind Animated Mascot Login that Covers Its Eyes
- 18Tailwind Accessible Compact Login Modal with Scale-In
- 19Tailwind Glassmorphism Login Card with backdrop-filter
- 20Tailwind Multi-Step Login Wizard with Radio-Driven Track
- 21Tailwind Animated Conic Gradient Border Login Card
- 22Tailwind Secure Vault Login with user-invalid Error State
- 23Tailwind Neo-Brutalist Login Form with Hard Offset Shadow
- 24Tailwind Show Hide Password Toggle with aria-pressed
- 25Tailwind OTP Code Input Grid with Auto-Advance
- 26Tailwind Password Strength Meter with data-score Variants
- 27Tailwind Numeric PIN Pad Login for Kiosks and POS
- 28Tailwind Inline Form Validation with user-valid and user-invalid
- 29Tailwind Particle Constellation Login over Canvas
- 30Tailwind Biometric Face ID Prompt with Pulse Ripples
Tailwind Terminal CLI Prompt Login Form
An authentic CLI login for dev-tools, DevOps panels and security apps: monospaced type, a traffic-light window bar, a blinking block cursor and raw prompt-style inputs with no chrome. The port keeps every affordance the original argued for — including a visible focus treatment on borderless fields, which is the easy thing to lose in a terminal aesthetic.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tlf-12 w-full min-h-svh grid place-items-center bg-tlf12-stage font-tlf12-mono p-6">
<form novalidate class="w-[min(460px,100%)] rounded-xl overflow-hidden bg-tlf12-card border border-tlf12-edge shadow-[0_30px_70px_-44px_black]">
<div class="flex items-center gap-2 px-4 py-3 bg-tlf12-bar border-b border-tlf12-edge">
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot1"></span>
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot2"></span>
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot3"></span>
<span class="ml-2 text-xs text-tlf12-mut">auth@northwind — ssh</span>
</div>
<div class="flex flex-col gap-4 p-6">
<p class="text-[13px]/[1.6] text-tlf12-mut">Authentication required. Provide credentials to continue.</p>
<label class="flex items-center gap-2 pb-2 border-b border-transparent transition-colors duration-150 focus-within:border-tlf12-caret before:content-['$'] before:font-bold before:text-tlf12-prompt">
<span class="text-[13px] text-tlf12-label select-none">username</span>
<input type="text" autocomplete="username" placeholder="ana.reyes" required class="flex-1 min-w-0 h-8 bg-transparent border-0 text-[14.5px] text-tlf12-ink placeholder:text-tlf12-ph focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tlf12-caret">
</label>
<label class="flex items-center gap-2 pb-2 border-b border-transparent transition-colors duration-150 focus-within:border-tlf12-caret before:content-['$'] before:font-bold before:text-tlf12-prompt">
<span class="text-[13px] text-tlf12-label select-none">password</span>
<input type="password" autocomplete="current-password" placeholder="••••••••" required class="flex-1 min-w-0 h-8 bg-transparent border-0 text-[14.5px] text-tlf12-ink placeholder:text-tlf12-ph focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tlf12-caret">
<span aria-hidden="true" class="w-2 h-[17px] bg-tlf12-caret animate-tlf12-blink motion-reduce:animate-none"></span>
</label>
<button type="submit" class="flex items-center justify-center gap-2 min-h-11 mt-1 rounded-md cursor-pointer bg-tlf12-btn border border-tlf12-prompt text-tlf12-prompt text-[14px] font-bold tracking-wide transition-colors duration-150 hover:bg-tlf12-btnhover focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tlf12-prompt"><span aria-hidden="true">→</span> ./authenticate</button>
<p class="text-[12px] text-tlf12-mut">Need access? <a href="#" class="text-tlf12-caret no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tlf12-caret">request an account</a></p>
</div>
</form>
</section><section class="tlf-12 w-full min-h-svh grid place-items-center bg-tlf12-stage font-tlf12-mono p-6">
<form novalidate class="w-[min(460px,100%)] rounded-xl overflow-hidden bg-tlf12-card border border-tlf12-edge shadow-[0_30px_70px_-44px_black]">
<div class="flex items-center gap-2 px-4 py-3 bg-tlf12-bar border-b border-tlf12-edge">
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot1"></span>
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot2"></span>
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot3"></span>
<span class="ml-2 text-xs text-tlf12-mut">auth@northwind — ssh</span>
</div>
<div class="flex flex-col gap-4 p-6">
<p class="text-[13px]/[1.6] text-tlf12-mut">Authentication required. Provide credentials to continue.</p>
<label class="flex items-center gap-2 pb-2 border-b border-transparent transition-colors duration-150 focus-within:border-tlf12-caret before:content-['$'] before:font-bold before:text-tlf12-prompt">
<span class="text-[13px] text-tlf12-label select-none">username</span>
<input type="text" autocomplete="username" placeholder="ana.reyes" required class="flex-1 min-w-0 h-8 bg-transparent border-0 text-[14.5px] text-tlf12-ink placeholder:text-tlf12-ph focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tlf12-caret">
</label>
<label class="flex items-center gap-2 pb-2 border-b border-transparent transition-colors duration-150 focus-within:border-tlf12-caret before:content-['$'] before:font-bold before:text-tlf12-prompt">
<span class="text-[13px] text-tlf12-label select-none">password</span>
<input type="password" autocomplete="current-password" placeholder="••••••••" required class="flex-1 min-w-0 h-8 bg-transparent border-0 text-[14.5px] text-tlf12-ink placeholder:text-tlf12-ph focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tlf12-caret">
<span aria-hidden="true" class="w-2 h-[17px] bg-tlf12-caret animate-tlf12-blink motion-reduce:animate-none"></span>
</label>
<button type="submit" class="flex items-center justify-center gap-2 min-h-11 mt-1 rounded-md cursor-pointer bg-tlf12-btn border border-tlf12-prompt text-tlf12-prompt text-[14px] font-bold tracking-wide transition-colors duration-150 hover:bg-tlf12-btnhover focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tlf12-prompt"><span aria-hidden="true">→</span> ./authenticate</button>
<p class="text-[12px] text-tlf12-mut">Need access? <a href="#" class="text-tlf12-caret no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tlf12-caret">request an account</a></p>
</div>
</form>
</section>@import "tailwindcss";
@theme {
--color-tlf12-stage: #07090c;
--color-tlf12-stage: oklch(0.13 0.008 250);
--color-tlf12-card: #0d1117;
--color-tlf12-card: oklch(0.17 0.01 250);
--color-tlf12-bar: #151a21;
--color-tlf12-bar: oklch(0.21 0.01 250);
--color-tlf12-edge: #232a34;
--color-tlf12-edge: oklch(0.27 0.012 250);
--color-tlf12-btn: #101820;
--color-tlf12-btn: oklch(0.19 0.015 160 / 0.6);
--color-tlf12-btnhover: #16251d;
--color-tlf12-btnhover: oklch(0.24 0.04 150 / 0.7);
--color-tlf12-ink: #e8edf5;
--color-tlf12-ink: oklch(0.94 0.008 250);
--color-tlf12-label: #b8c1cf;
--color-tlf12-label: oklch(0.81 0.015 250);
--color-tlf12-mut: #9aa4b4;
--color-tlf12-mut: oklch(0.71 0.018 250);
--color-tlf12-ph: #6f7a8b;
--color-tlf12-ph: oklch(0.57 0.02 250);
--color-tlf12-prompt: #5fd98f;
--color-tlf12-prompt: oklch(0.78 0.16 145);
--color-tlf12-caret: #f0b74d;
--color-tlf12-caret: oklch(0.8 0.15 80);
--color-tlf12-dot1: #ef6a5e;
--color-tlf12-dot1: oklch(0.68 0.18 25);
--color-tlf12-dot2: #f0b74d;
--color-tlf12-dot2: oklch(0.8 0.15 80);
--color-tlf12-dot3: #5fd98f;
--color-tlf12-dot3: oklch(0.78 0.16 145);
--font-tlf12-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--animate-tlf12-blink: tlf-12-blink 1s steps(1, end) infinite;
}
@keyframes tlf-12-blink {
0%,
50% {
opacity: 1;
}
50.01%,
100% {
opacity: 0;
}
}
.tlf-12 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}@import "tailwindcss";
@theme {
--color-tlf12-stage: #07090c;
--color-tlf12-stage: oklch(0.13 0.008 250);
--color-tlf12-card: #0d1117;
--color-tlf12-card: oklch(0.17 0.01 250);
--color-tlf12-bar: #151a21;
--color-tlf12-bar: oklch(0.21 0.01 250);
--color-tlf12-edge: #232a34;
--color-tlf12-edge: oklch(0.27 0.012 250);
--color-tlf12-btn: #101820;
--color-tlf12-btn: oklch(0.19 0.015 160 / 0.6);
--color-tlf12-btnhover: #16251d;
--color-tlf12-btnhover: oklch(0.24 0.04 150 / 0.7);
--color-tlf12-ink: #e8edf5;
--color-tlf12-ink: oklch(0.94 0.008 250);
--color-tlf12-label: #b8c1cf;
--color-tlf12-label: oklch(0.81 0.015 250);
--color-tlf12-mut: #9aa4b4;
--color-tlf12-mut: oklch(0.71 0.018 250);
--color-tlf12-ph: #6f7a8b;
--color-tlf12-ph: oklch(0.57 0.02 250);
--color-tlf12-prompt: #5fd98f;
--color-tlf12-prompt: oklch(0.78 0.16 145);
--color-tlf12-caret: #f0b74d;
--color-tlf12-caret: oklch(0.8 0.15 80);
--color-tlf12-dot1: #ef6a5e;
--color-tlf12-dot1: oklch(0.68 0.18 25);
--color-tlf12-dot2: #f0b74d;
--color-tlf12-dot2: oklch(0.8 0.15 80);
--color-tlf12-dot3: #5fd98f;
--color-tlf12-dot3: oklch(0.78 0.16 145);
--font-tlf12-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--animate-tlf12-blink: tlf-12-blink 1s steps(1, end) infinite;
}
@keyframes tlf-12-blink {
0%,
50% {
opacity: 1;
}
50.01%,
100% {
opacity: 0;
}
}
.tlf-12 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}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-tlf12-stage: #07090c;
--color-tlf12-stage: oklch(0.13 0.008 250);
--color-tlf12-card: #0d1117;
--color-tlf12-card: oklch(0.17 0.01 250);
--color-tlf12-bar: #151a21;
--color-tlf12-bar: oklch(0.21 0.01 250);
--color-tlf12-edge: #232a34;
--color-tlf12-edge: oklch(0.27 0.012 250);
--color-tlf12-btn: #101820;
--color-tlf12-btn: oklch(0.19 0.015 160 / 0.6);
--color-tlf12-btnhover: #16251d;
--color-tlf12-btnhover: oklch(0.24 0.04 150 / 0.7);
--color-tlf12-ink: #e8edf5;
--color-tlf12-ink: oklch(0.94 0.008 250);
--color-tlf12-label: #b8c1cf;
--color-tlf12-label: oklch(0.81 0.015 250);
--color-tlf12-mut: #9aa4b4;
--color-tlf12-mut: oklch(0.71 0.018 250);
--color-tlf12-ph: #6f7a8b;
--color-tlf12-ph: oklch(0.57 0.02 250);
--color-tlf12-prompt: #5fd98f;
--color-tlf12-prompt: oklch(0.78 0.16 145);
--color-tlf12-caret: #f0b74d;
--color-tlf12-caret: oklch(0.8 0.15 80);
--color-tlf12-dot1: #ef6a5e;
--color-tlf12-dot1: oklch(0.68 0.18 25);
--color-tlf12-dot2: #f0b74d;
--color-tlf12-dot2: oklch(0.8 0.15 80);
--color-tlf12-dot3: #5fd98f;
--color-tlf12-dot3: oklch(0.78 0.16 145);
--font-tlf12-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--animate-tlf12-blink: tlf-12-blink 1s steps(1, end) infinite;
}
@keyframes tlf-12-blink {
0%,
50% {
opacity: 1;
}
50.01%,
100% {
opacity: 0;
}
}
.tlf-12 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}@import "tailwindcss";
@theme {
--color-tlf12-stage: #07090c;
--color-tlf12-stage: oklch(0.13 0.008 250);
--color-tlf12-card: #0d1117;
--color-tlf12-card: oklch(0.17 0.01 250);
--color-tlf12-bar: #151a21;
--color-tlf12-bar: oklch(0.21 0.01 250);
--color-tlf12-edge: #232a34;
--color-tlf12-edge: oklch(0.27 0.012 250);
--color-tlf12-btn: #101820;
--color-tlf12-btn: oklch(0.19 0.015 160 / 0.6);
--color-tlf12-btnhover: #16251d;
--color-tlf12-btnhover: oklch(0.24 0.04 150 / 0.7);
--color-tlf12-ink: #e8edf5;
--color-tlf12-ink: oklch(0.94 0.008 250);
--color-tlf12-label: #b8c1cf;
--color-tlf12-label: oklch(0.81 0.015 250);
--color-tlf12-mut: #9aa4b4;
--color-tlf12-mut: oklch(0.71 0.018 250);
--color-tlf12-ph: #6f7a8b;
--color-tlf12-ph: oklch(0.57 0.02 250);
--color-tlf12-prompt: #5fd98f;
--color-tlf12-prompt: oklch(0.78 0.16 145);
--color-tlf12-caret: #f0b74d;
--color-tlf12-caret: oklch(0.8 0.15 80);
--color-tlf12-dot1: #ef6a5e;
--color-tlf12-dot1: oklch(0.68 0.18 25);
--color-tlf12-dot2: #f0b74d;
--color-tlf12-dot2: oklch(0.8 0.15 80);
--color-tlf12-dot3: #5fd98f;
--color-tlf12-dot3: oklch(0.78 0.16 145);
--font-tlf12-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--animate-tlf12-blink: tlf-12-blink 1s steps(1, end) infinite;
}
@keyframes tlf-12-blink {
0%,
50% {
opacity: 1;
}
50.01%,
100% {
opacity: 0;
}
}
.tlf-12 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}<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;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=JetBrains+Mono:wght@400;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
before:content-['$']is the same move the breadcrumb collection makes with separators, for the same reason: a decorative glyph belongs on the element that shows it and out of the accessibility tree.focus-within:border-tlf12-careton the row plusfocus-visible:outline-offset-4on the input gives two layers of focus signal on a field with no border of its own — worth the extra utility on a chrome-free design.--animate-tlf12-blinkcarries thesteps(1, end)function inside the token, so the snap is part of the theme rather than something a future edit can smooth out by accident.- UI change from the CSS original: JetBrains Mono replaces the system monospace stack, the prompt green moved to
oklch(0.78 0.16 145)(9.4:1 on the card, versus classic terminal green's glare), the button became a bordered 44px control with a real label rather than a bare submit, and the field placeholder lifted to 4.6:1.
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 Terminal CLI Prompt Login Form
Source: https://codefronts.com/components/tailwind-css-login-forms/tailwind-terminal-cli-prompt-login-form/
An authentic CLI login for dev-tools, DevOps panels and security apps: monospaced type, a traffic-light window bar, a blinking block cursor and raw prompt-style inputs with no chrome. The port keeps every affordance the original argued for — including a visible focus treatment on borderless fields, which is the easy thing to lose in a terminal aesthetic.
## HTML
```html
<section class="tlf-12 w-full min-h-svh grid place-items-center bg-tlf12-stage font-tlf12-mono p-6">
<form novalidate class="w-[min(460px,100%)] rounded-xl overflow-hidden bg-tlf12-card border border-tlf12-edge shadow-[0_30px_70px_-44px_black]">
<div class="flex items-center gap-2 px-4 py-3 bg-tlf12-bar border-b border-tlf12-edge">
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot1"></span>
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot2"></span>
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot3"></span>
<span class="ml-2 text-xs text-tlf12-mut">auth@northwind — ssh</span>
</div>
<div class="flex flex-col gap-4 p-6">
<p class="text-[13px]/[1.6] text-tlf12-mut">Authentication required. Provide credentials to continue.</p>
<label class="flex items-center gap-2 pb-2 border-b border-transparent transition-colors duration-150 focus-within:border-tlf12-caret before:content-['$'] before:font-bold before:text-tlf12-prompt">
<span class="text-[13px] text-tlf12-label select-none">username</span>
<input type="text" autocomplete="username" placeholder="ana.reyes" required class="flex-1 min-w-0 h-8 bg-transparent border-0 text-[14.5px] text-tlf12-ink placeholder:text-tlf12-ph focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tlf12-caret">
</label>
<label class="flex items-center gap-2 pb-2 border-b border-transparent transition-colors duration-150 focus-within:border-tlf12-caret before:content-['$'] before:font-bold before:text-tlf12-prompt">
<span class="text-[13px] text-tlf12-label select-none">password</span>
<input type="password" autocomplete="current-password" placeholder="••••••••" required class="flex-1 min-w-0 h-8 bg-transparent border-0 text-[14.5px] text-tlf12-ink placeholder:text-tlf12-ph focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tlf12-caret">
<span aria-hidden="true" class="w-2 h-[17px] bg-tlf12-caret animate-tlf12-blink motion-reduce:animate-none"></span>
</label>
<button type="submit" class="flex items-center justify-center gap-2 min-h-11 mt-1 rounded-md cursor-pointer bg-tlf12-btn border border-tlf12-prompt text-tlf12-prompt text-[14px] font-bold tracking-wide transition-colors duration-150 hover:bg-tlf12-btnhover focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tlf12-prompt"><span aria-hidden="true">→</span> ./authenticate</button>
<p class="text-[12px] text-tlf12-mut">Need access? <a href="#" class="text-tlf12-caret no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tlf12-caret">request an account</a></p>
</div>
</form>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tlf12-stage: #07090c;
--color-tlf12-stage: oklch(0.13 0.008 250);
--color-tlf12-card: #0d1117;
--color-tlf12-card: oklch(0.17 0.01 250);
--color-tlf12-bar: #151a21;
--color-tlf12-bar: oklch(0.21 0.01 250);
--color-tlf12-edge: #232a34;
--color-tlf12-edge: oklch(0.27 0.012 250);
--color-tlf12-btn: #101820;
--color-tlf12-btn: oklch(0.19 0.015 160 / 0.6);
--color-tlf12-btnhover: #16251d;
--color-tlf12-btnhover: oklch(0.24 0.04 150 / 0.7);
--color-tlf12-ink: #e8edf5;
--color-tlf12-ink: oklch(0.94 0.008 250);
--color-tlf12-label: #b8c1cf;
--color-tlf12-label: oklch(0.81 0.015 250);
--color-tlf12-mut: #9aa4b4;
--color-tlf12-mut: oklch(0.71 0.018 250);
--color-tlf12-ph: #6f7a8b;
--color-tlf12-ph: oklch(0.57 0.02 250);
--color-tlf12-prompt: #5fd98f;
--color-tlf12-prompt: oklch(0.78 0.16 145);
--color-tlf12-caret: #f0b74d;
--color-tlf12-caret: oklch(0.8 0.15 80);
--color-tlf12-dot1: #ef6a5e;
--color-tlf12-dot1: oklch(0.68 0.18 25);
--color-tlf12-dot2: #f0b74d;
--color-tlf12-dot2: oklch(0.8 0.15 80);
--color-tlf12-dot3: #5fd98f;
--color-tlf12-dot3: oklch(0.78 0.16 145);
--font-tlf12-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--animate-tlf12-blink: tlf-12-blink 1s steps(1, end) infinite;
}
@keyframes tlf-12-blink {
0%,
50% {
opacity: 1;
}
50.01%,
100% {
opacity: 0;
}
}
.tlf-12 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}
```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 Terminal CLI Prompt Login Form
Source: https://codefronts.com/components/tailwind-css-login-forms/tailwind-terminal-cli-prompt-login-form/
An authentic CLI login for dev-tools, DevOps panels and security apps: monospaced type, a traffic-light window bar, a blinking block cursor and raw prompt-style inputs with no chrome. The port keeps every affordance the original argued for — including a visible focus treatment on borderless fields, which is the easy thing to lose in a terminal aesthetic.
## HTML
```html
<section class="tlf-12 w-full min-h-svh grid place-items-center bg-tlf12-stage font-tlf12-mono p-6">
<form novalidate class="w-[min(460px,100%)] rounded-xl overflow-hidden bg-tlf12-card border border-tlf12-edge shadow-[0_30px_70px_-44px_black]">
<div class="flex items-center gap-2 px-4 py-3 bg-tlf12-bar border-b border-tlf12-edge">
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot1"></span>
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot2"></span>
<span aria-hidden="true" class="size-3 rounded-full bg-tlf12-dot3"></span>
<span class="ml-2 text-xs text-tlf12-mut">auth@northwind — ssh</span>
</div>
<div class="flex flex-col gap-4 p-6">
<p class="text-[13px]/[1.6] text-tlf12-mut">Authentication required. Provide credentials to continue.</p>
<label class="flex items-center gap-2 pb-2 border-b border-transparent transition-colors duration-150 focus-within:border-tlf12-caret before:content-['$'] before:font-bold before:text-tlf12-prompt">
<span class="text-[13px] text-tlf12-label select-none">username</span>
<input type="text" autocomplete="username" placeholder="ana.reyes" required class="flex-1 min-w-0 h-8 bg-transparent border-0 text-[14.5px] text-tlf12-ink placeholder:text-tlf12-ph focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tlf12-caret">
</label>
<label class="flex items-center gap-2 pb-2 border-b border-transparent transition-colors duration-150 focus-within:border-tlf12-caret before:content-['$'] before:font-bold before:text-tlf12-prompt">
<span class="text-[13px] text-tlf12-label select-none">password</span>
<input type="password" autocomplete="current-password" placeholder="••••••••" required class="flex-1 min-w-0 h-8 bg-transparent border-0 text-[14.5px] text-tlf12-ink placeholder:text-tlf12-ph focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tlf12-caret">
<span aria-hidden="true" class="w-2 h-[17px] bg-tlf12-caret animate-tlf12-blink motion-reduce:animate-none"></span>
</label>
<button type="submit" class="flex items-center justify-center gap-2 min-h-11 mt-1 rounded-md cursor-pointer bg-tlf12-btn border border-tlf12-prompt text-tlf12-prompt text-[14px] font-bold tracking-wide transition-colors duration-150 hover:bg-tlf12-btnhover focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tlf12-prompt"><span aria-hidden="true">→</span> ./authenticate</button>
<p class="text-[12px] text-tlf12-mut">Need access? <a href="#" class="text-tlf12-caret no-underline hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tlf12-caret">request an account</a></p>
</div>
</form>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tlf12-stage: #07090c;
--color-tlf12-stage: oklch(0.13 0.008 250);
--color-tlf12-card: #0d1117;
--color-tlf12-card: oklch(0.17 0.01 250);
--color-tlf12-bar: #151a21;
--color-tlf12-bar: oklch(0.21 0.01 250);
--color-tlf12-edge: #232a34;
--color-tlf12-edge: oklch(0.27 0.012 250);
--color-tlf12-btn: #101820;
--color-tlf12-btn: oklch(0.19 0.015 160 / 0.6);
--color-tlf12-btnhover: #16251d;
--color-tlf12-btnhover: oklch(0.24 0.04 150 / 0.7);
--color-tlf12-ink: #e8edf5;
--color-tlf12-ink: oklch(0.94 0.008 250);
--color-tlf12-label: #b8c1cf;
--color-tlf12-label: oklch(0.81 0.015 250);
--color-tlf12-mut: #9aa4b4;
--color-tlf12-mut: oklch(0.71 0.018 250);
--color-tlf12-ph: #6f7a8b;
--color-tlf12-ph: oklch(0.57 0.02 250);
--color-tlf12-prompt: #5fd98f;
--color-tlf12-prompt: oklch(0.78 0.16 145);
--color-tlf12-caret: #f0b74d;
--color-tlf12-caret: oklch(0.8 0.15 80);
--color-tlf12-dot1: #ef6a5e;
--color-tlf12-dot1: oklch(0.68 0.18 25);
--color-tlf12-dot2: #f0b74d;
--color-tlf12-dot2: oklch(0.8 0.15 80);
--color-tlf12-dot3: #5fd98f;
--color-tlf12-dot3: oklch(0.78 0.16 145);
--font-tlf12-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
--animate-tlf12-blink: tlf-12-blink 1s steps(1, end) infinite;
}
@keyframes tlf-12-blink {
0%,
50% {
opacity: 1;
}
50.01%,
100% {
opacity: 0;
}
}
.tlf-12 {
width: 100%;
min-height: 100svh;
color-scheme: dark;
}
```How this works
The prompt is a pseudo-element on the row. before:content-['$'] plus before:mr-2 puts the shell glyph outside the accessibility tree — a screen reader announces “Username, edit text”, not “dollar sign username”. Same technique the breadcrumb collection uses for separators, same reason.
The cursor blinks in CSS. A steps(1, end) animation on a 8×17px block, so it snaps on and off like a real terminal caret rather than fading. No interval, no timer, no JS.
Focus is visible without a border. Each row's bottom border is transparent at rest and takes the caret colour under focus-within:, and the input keeps a real focus-visible: outline offset into the row. Stripping chrome is an aesthetic choice; stripping focus is a bug.
Make it yours
- Palette:
--color-tlf12-prompt(green),--color-tlf12-caret(amber),--color-tlf12-ink. - Prompt glyph:
before:content-['$']→['>']or['⋆']. - Blink rate: the duration in
--animate-tlf12-blink. - Window title: plain text in the title bar, next to the three dots.
Gotchas — read before shipping
- Keep a visible focus treatment on the raw inputs. A borderless field with no focus state is unusable by keyboard, and the terminal look does not excuse it.
- Terminal green on black must still hit 4.5:1 for anything a user reads —
oklch(0.78 0.16 145)here, not the classic#0f0. steps(1, end), notlinear, or the cursor fades in and out and stops reading as a caret.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Monospace stacks, @keyframes and :focus-within are universally supported; the floor is Tailwind v4's generated sheet.