30 Tailwind CSS Login Forms
02 / 30

All 30 in 30 Tailwind CSS Login Forms

  1. 01Tailwind Split-Screen Brand Hero Login Form
  2. 02Tailwind Multi-Tenant Workspace Account Switcher
  3. 03Tailwind Floating Label Login Form with peer Variants
  4. 04Tailwind Web3 Wallet Connect Login Grid
  5. 05Tailwind Minimalist Fintech Login Card with Layered Shadow
  6. 06Tailwind OAuth Social Login Form with Brand SVG Buttons
  7. 07Tailwind Passwordless Magic Link Login with data-state Machine
  8. 08Tailwind Aurora Glow Login Card with Drifting Blur Blobs
  9. 09Tailwind Neon Synthwave Arcade Login Form
  10. 10Tailwind Sliding Login and Sign Up Panel with peer-checked
  11. 11Tailwind 3D Flip Login Card with Password Reset Back Face
  12. 12Tailwind Terminal CLI Prompt Login Form
  13. 13Tailwind Floating Pill Login Widget Docked Over App Content
  14. 14Tailwind Gradient Border Login Card with background-clip
  15. 15Tailwind Slide-Over Side Panel Login without JavaScript
  16. 16Tailwind Social-First Sign Up with Brand-Compliant Buttons
  17. 17Tailwind Animated Mascot Login that Covers Its Eyes
  18. 18Tailwind Accessible Compact Login Modal with Scale-In
  19. 19Tailwind Glassmorphism Login Card with backdrop-filter
  20. 20Tailwind Multi-Step Login Wizard with Radio-Driven Track
  21. 21Tailwind Animated Conic Gradient Border Login Card
  22. 22Tailwind Secure Vault Login with user-invalid Error State
  23. 23Tailwind Neo-Brutalist Login Form with Hard Offset Shadow
  24. 24Tailwind Show Hide Password Toggle with aria-pressed
  25. 25Tailwind OTP Code Input Grid with Auto-Advance
  26. 26Tailwind Password Strength Meter with data-score Variants
  27. 27Tailwind Numeric PIN Pad Login for Kiosks and POS
  28. 28Tailwind Inline Form Validation with user-valid and user-invalid
  29. 29Tailwind Particle Constellation Login over Canvas
  30. 30Tailwind Biometric Face ID Prompt with Pulse Ripples
Pure TailwindMIT licensed

Tailwind Multi-Tenant Workspace Account Switcher

The B2B enterprise front door (think Slack or AWS): a returning user picks which workspace to enter from a stack of profile rows, each with a tinted avatar and a role badge. The port keeps the original's best idea — one --tint hue per row drives avatar, badge, hover and ring — because a per-row hue is data, not a design-scale value, and belongs in a style attribute rather than four utilities.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="tlf-02 w-full min-h-svh grid place-items-center bg-tlf02-stage font-tlf02-sans px-5 py-8">
  <div class="w-[min(420px,100%)] p-6 bg-white border border-tlf02-edge rounded-[20px] shadow-[0_24px_56px_-38px_oklch(0.25_0.06_265/0.55)]">
    <header class="mb-4">
      <h1 class="text-xl font-bold tracking-tight text-tlf02-ink">Choose a workspace</h1>
      <p class="mt-1 text-[13px] text-tlf02-mut">You&rsquo;re signed in as ana@lumen.io</p>
    </header>
    <ul class="flex flex-col gap-2 list-none m-0 p-0">
      <li style="--tint:264">
        <a href="#" class="flex items-center gap-3 min-h-11 p-3 rounded-xl no-underline border border-transparent transition-[background-color,border-color,translate] duration-150 hover:translate-x-0.5 hover:bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_8%,white)] hover:border-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_30%,white)] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.58_0.19_var(--tint)/0.55)] motion-reduce:transition-colors motion-reduce:hover:translate-x-0">
          <span aria-hidden="true" class="grid place-items-center flex-none size-11 rounded-full text-sm font-bold text-white bg-[oklch(0.58_0.16_var(--tint))]">LM</span>
          <span class="flex-1 min-w-0 flex flex-col gap-0.5">
            <span class="text-[15px] font-semibold text-tlf02-ink truncate">Lumen Design</span>
            <span class="text-[12.5px] text-tlf02-mut">lumen.slack.com</span>
          </span>
          <span class="flex-none text-[11px] font-bold tracking-wide px-2.5 py-1 rounded-full text-[oklch(0.42_0.16_var(--tint))] bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_16%,white)]">Owner</span>
        </a>
      </li>
      <li style="--tint:160">
        <a href="#" class="flex items-center gap-3 min-h-11 p-3 rounded-xl no-underline border border-transparent transition-[background-color,border-color,translate] duration-150 hover:translate-x-0.5 hover:bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_8%,white)] hover:border-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_30%,white)] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.58_0.19_var(--tint)/0.55)] motion-reduce:transition-colors motion-reduce:hover:translate-x-0">
          <span aria-hidden="true" class="grid place-items-center flex-none size-11 rounded-full text-sm font-bold text-white bg-[oklch(0.58_0.16_var(--tint))]">AC</span>
          <span class="flex-1 min-w-0 flex flex-col gap-0.5">
            <span class="text-[15px] font-semibold text-tlf02-ink truncate">Acme Corp</span>
            <span class="text-[12.5px] text-tlf02-mut">acme.slack.com</span>
          </span>
          <span class="flex-none text-[11px] font-bold tracking-wide px-2.5 py-1 rounded-full text-[oklch(0.42_0.16_var(--tint))] bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_16%,white)]">Admin</span>
        </a>
      </li>
      <li style="--tint:30">
        <a href="#" class="flex items-center gap-3 min-h-11 p-3 rounded-xl no-underline border border-transparent transition-[background-color,border-color,translate] duration-150 hover:translate-x-0.5 hover:bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_8%,white)] hover:border-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_30%,white)] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.58_0.19_var(--tint)/0.55)] motion-reduce:transition-colors motion-reduce:hover:translate-x-0">
          <span aria-hidden="true" class="grid place-items-center flex-none size-11 rounded-full text-sm font-bold text-white bg-[oklch(0.58_0.16_var(--tint))]">NW</span>
          <span class="flex-1 min-w-0 flex flex-col gap-0.5">
            <span class="text-[15px] font-semibold text-tlf02-ink truncate">Northwind</span>
            <span class="text-[12.5px] text-tlf02-mut">northwind.slack.com</span>
          </span>
          <span class="flex-none text-[11px] font-bold tracking-wide px-2.5 py-1 rounded-full text-[oklch(0.42_0.16_var(--tint))] bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_16%,white)]">Member</span>
        </a>
      </li>
    </ul>
    <a href="#" class="flex items-center justify-center gap-2 min-h-11 mt-4 p-3 rounded-xl border-[1.5px] border-dashed border-tlf02-dash text-sm font-semibold text-tlf02-mut no-underline transition-colors duration-150 hover:border-tlf02-acc hover:text-tlf02-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tlf02-ring"><span aria-hidden="true" class="text-[17px] leading-none">+</span> Add another account</a>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tlf02-stage: #f4f5f9;
  --color-tlf02-stage: oklch(0.96 0.005 270);
  --color-tlf02-edge: #e7e9f0;
  --color-tlf02-edge: oklch(0.92 0.006 270);
  --color-tlf02-dash: #cfd4e2;
  --color-tlf02-dash: oklch(0.85 0.012 270);
  --color-tlf02-ink: #161c2e;
  --color-tlf02-ink: oklch(0.23 0.04 270);
  --color-tlf02-mut: #656c86;
  --color-tlf02-mut: oklch(0.51 0.03 270);
  --color-tlf02-acc: #5a63d8;
  --color-tlf02-acc: oklch(0.58 0.19 264);
  --color-tlf02-ring: #c9cdf4;
  --color-tlf02-ring: oklch(0.58 0.19 264 / 0.5);
  --color-tlf02-wash: #f0f1f6;
  --color-tlf02-wash: oklch(0.94 0.005 270);
  --font-tlf02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}

.tlf-02 {
  width: 100%;
  min-height: 100svh;
}
/* color-mix() fallback: browsers without it get a neutral wash rather than no hover at all. */

@supports not (background: color-mix(in oklch, red 8%, white)) {
  .tlf-02 a:hover {
    background: var(--color-tlf02-wash);
    border-color: var(--color-tlf02-dash);
  }
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<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.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-tlf02-stage: #f4f5f9;
  --color-tlf02-stage: oklch(0.96 0.005 270);
  --color-tlf02-edge: #e7e9f0;
  --color-tlf02-edge: oklch(0.92 0.006 270);
  --color-tlf02-dash: #cfd4e2;
  --color-tlf02-dash: oklch(0.85 0.012 270);
  --color-tlf02-ink: #161c2e;
  --color-tlf02-ink: oklch(0.23 0.04 270);
  --color-tlf02-mut: #656c86;
  --color-tlf02-mut: oklch(0.51 0.03 270);
  --color-tlf02-acc: #5a63d8;
  --color-tlf02-acc: oklch(0.58 0.19 264);
  --color-tlf02-ring: #c9cdf4;
  --color-tlf02-ring: oklch(0.58 0.19 264 / 0.5);
  --color-tlf02-wash: #f0f1f6;
  --color-tlf02-wash: oklch(0.94 0.005 270);
  --font-tlf02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}

.tlf-02 {
  width: 100%;
  min-height: 100svh;
}
/* color-mix() fallback: browsers without it get a neutral wash rather than no hover at all. */

@supports not (background: color-mix(in oklch, red 8%, white)) {
  .tlf-02 a:hover {
    background: var(--color-tlf02-wash);
    border-color: var(--color-tlf02-dash);
  }
}
3Fonts used by this demooptional — skip if you have your own type stack
<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.

  • This is the demo that proves not everything should become a utility. Three rows × four tinted properties would be twelve arbitrary colour classes; one --tint on the <li> plus var(--tint) inside the utilities keeps it at one number per row, which is exactly what the CSS original did well.
  • truncate replaces the original's three-declaration white-space/overflow/text-overflow stack, and min-w-0 next to it is the non-obvious part: without it the flex child refuses to shrink and the badge leaves the card.
  • The @supports not (background: color-mix(...)) block is one of the few things utilities cannot express — feature queries have no variant form, so it stays in the stylesheet.
  • UI change from the CSS original: rows gained min-h-11 (44px), the badge text darkened to oklch(0.42) for 4.5:1 on its own 16% wash, and the muted email colour lifted from #8a91aa to oklch(0.51 0.03 270).
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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 Multi-Tenant Workspace Account Switcher
Source: https://codefronts.com/components/tailwind-css-login-forms/tailwind-multi-tenant-workspace-account-switcher/

The B2B enterprise front door (think Slack or AWS): a returning user picks which workspace to enter from a stack of profile rows, each with a tinted avatar and a role badge. The port keeps the original's best idea &mdash; one --tint hue per row drives avatar, badge, hover and ring &mdash; because a per-row hue is data, not a design-scale value, and belongs in a style attribute rather than four utilities.
## HTML
```html
<section class="tlf-02 w-full min-h-svh grid place-items-center bg-tlf02-stage font-tlf02-sans px-5 py-8">
  <div class="w-[min(420px,100%)] p-6 bg-white border border-tlf02-edge rounded-[20px] shadow-[0_24px_56px_-38px_oklch(0.25_0.06_265/0.55)]">
    <header class="mb-4">
      <h1 class="text-xl font-bold tracking-tight text-tlf02-ink">Choose a workspace</h1>
      <p class="mt-1 text-[13px] text-tlf02-mut">You&rsquo;re signed in as ana@lumen.io</p>
    </header>
    <ul class="flex flex-col gap-2 list-none m-0 p-0">
      <li style="--tint:264">
        <a href="#" class="flex items-center gap-3 min-h-11 p-3 rounded-xl no-underline border border-transparent transition-[background-color,border-color,translate] duration-150 hover:translate-x-0.5 hover:bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_8%,white)] hover:border-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_30%,white)] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.58_0.19_var(--tint)/0.55)] motion-reduce:transition-colors motion-reduce:hover:translate-x-0">
          <span aria-hidden="true" class="grid place-items-center flex-none size-11 rounded-full text-sm font-bold text-white bg-[oklch(0.58_0.16_var(--tint))]">LM</span>
          <span class="flex-1 min-w-0 flex flex-col gap-0.5">
            <span class="text-[15px] font-semibold text-tlf02-ink truncate">Lumen Design</span>
            <span class="text-[12.5px] text-tlf02-mut">lumen.slack.com</span>
          </span>
          <span class="flex-none text-[11px] font-bold tracking-wide px-2.5 py-1 rounded-full text-[oklch(0.42_0.16_var(--tint))] bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_16%,white)]">Owner</span>
        </a>
      </li>
      <li style="--tint:160">
        <a href="#" class="flex items-center gap-3 min-h-11 p-3 rounded-xl no-underline border border-transparent transition-[background-color,border-color,translate] duration-150 hover:translate-x-0.5 hover:bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_8%,white)] hover:border-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_30%,white)] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.58_0.19_var(--tint)/0.55)] motion-reduce:transition-colors motion-reduce:hover:translate-x-0">
          <span aria-hidden="true" class="grid place-items-center flex-none size-11 rounded-full text-sm font-bold text-white bg-[oklch(0.58_0.16_var(--tint))]">AC</span>
          <span class="flex-1 min-w-0 flex flex-col gap-0.5">
            <span class="text-[15px] font-semibold text-tlf02-ink truncate">Acme Corp</span>
            <span class="text-[12.5px] text-tlf02-mut">acme.slack.com</span>
          </span>
          <span class="flex-none text-[11px] font-bold tracking-wide px-2.5 py-1 rounded-full text-[oklch(0.42_0.16_var(--tint))] bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_16%,white)]">Admin</span>
        </a>
      </li>
      <li style="--tint:30">
        <a href="#" class="flex items-center gap-3 min-h-11 p-3 rounded-xl no-underline border border-transparent transition-[background-color,border-color,translate] duration-150 hover:translate-x-0.5 hover:bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_8%,white)] hover:border-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_30%,white)] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.58_0.19_var(--tint)/0.55)] motion-reduce:transition-colors motion-reduce:hover:translate-x-0">
          <span aria-hidden="true" class="grid place-items-center flex-none size-11 rounded-full text-sm font-bold text-white bg-[oklch(0.58_0.16_var(--tint))]">NW</span>
          <span class="flex-1 min-w-0 flex flex-col gap-0.5">
            <span class="text-[15px] font-semibold text-tlf02-ink truncate">Northwind</span>
            <span class="text-[12.5px] text-tlf02-mut">northwind.slack.com</span>
          </span>
          <span class="flex-none text-[11px] font-bold tracking-wide px-2.5 py-1 rounded-full text-[oklch(0.42_0.16_var(--tint))] bg-[color-mix(in_oklch,oklch(0.58_0.16_var(--tint))_16%,white)]">Member</span>
        </a>
      </li>
    </ul>
    <a href="#" class="flex items-center justify-center gap-2 min-h-11 mt-4 p-3 rounded-xl border-[1.5px] border-dashed border-tlf02-dash text-sm font-semibold text-tlf02-mut no-underline transition-colors duration-150 hover:border-tlf02-acc hover:text-tlf02-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tlf02-ring"><span aria-hidden="true" class="text-[17px] leading-none">+</span> Add another account</a>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tlf02-stage: #f4f5f9;
  --color-tlf02-stage: oklch(0.96 0.005 270);
  --color-tlf02-edge: #e7e9f0;
  --color-tlf02-edge: oklch(0.92 0.006 270);
  --color-tlf02-dash: #cfd4e2;
  --color-tlf02-dash: oklch(0.85 0.012 270);
  --color-tlf02-ink: #161c2e;
  --color-tlf02-ink: oklch(0.23 0.04 270);
  --color-tlf02-mut: #656c86;
  --color-tlf02-mut: oklch(0.51 0.03 270);
  --color-tlf02-acc: #5a63d8;
  --color-tlf02-acc: oklch(0.58 0.19 264);
  --color-tlf02-ring: #c9cdf4;
  --color-tlf02-ring: oklch(0.58 0.19 264 / 0.5);
  --color-tlf02-wash: #f0f1f6;
  --color-tlf02-wash: oklch(0.94 0.005 270);
  --font-tlf02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
}

.tlf-02 {
  width: 100%;
  min-height: 100svh;
}
/* color-mix() fallback: browsers without it get a neutral wash rather than no hover at all. */

@supports not (background: color-mix(in oklch, red 8%, white)) {
  .tlf-02 a:hover {
    background: var(--color-tlf02-wash);
    border-color: var(--color-tlf02-dash);
  }
}
```

How this works

Per-row data stays a custom property. Tailwind's answer to "three rows, three hues" is not three sets of colour utilities — it is one class list where every colour reads var(--tint), and the hue lands on the row as inline data. Add a fourth workspace and you copy a <li> and change one number.

color-mix() does the tinting Tailwind can't token-ise. An 8% wash of the row hue over white, and a 30% edge of the same, are both arbitrary values here rather than @theme entries, because they depend on a property the theme cannot see.

The whole row is the target. The <a> is the flex container, not a child of it, so the avatar, the name stack and the badge are all inside the click area — and min-w-0 plus truncate on the name column keeps a long workspace name from pushing the badge off the card.

Make it yours

  • Tint a workspace by changing its --tint hue angle — 264 indigo, 160 green, 30 amber.
  • Swap initials for real avatars: the flex row already reserves a size-11 slot.
  • Row density lives in two utilities, gap-2 on the list and p-3 on the row.
  • Make rows buttons instead of links if the switch posts rather than navigates — the class list is unchanged.

Gotchas — read before shipping

  • Keep the rows in a real <ul>: assistive tech announces "list, 3 items", which is the whole orientation cue on this screen.
  • Never let the role badge be colour-only — the text label is what a colour-blind user reads.
  • oklch(0.58 0.16 var(--tint)) inside an arbitrary utility needs the underscore escape for its spaces (oklch(0.58_0.16_var(--tint))); writing real spaces there silently drops the whole class.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

color-mix() in oklch is the gate (Chrome 111, Safari 16.4, Firefox 113). Without it the hover wash falls back to the untinted grey in --color-tlf02-wash.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Theme tokensset in @theme, used by a utility

HTML & JSno Tailwind involved

Search CodeFronts

Loading…