24 examples Responsive Uses JS beginner

24 CSS Login Form Designs with Live Demos

Twenty-four free CSS login form templates — covering glassmorphism, neon, dark mode, multi-step sign in, OTP code entry, biometric / passkey prompts, magic-link, password strength meters and more. Every form is hand-coded with semantic HTML, modern standards-based CSS (`:has()`, `:focus-within`, `@property`), and scoped class-based styles — JavaScript is used only when it adds real interaction. Live demos with copy-paste code, accessible defaults, and mobile-first responsive layouts.

24 unique forms WCAG-friendly accessible Mobile-first responsive MIT free to use
01 / 24
Aurora Glow
Pure CSS
Welcome back
Sign in to continue
No account? Create one
Glassmorphism login form on a drifting aurora gradient. Floating labels rise on focus and the submit button picks up a soft brand glow on hover.
.lf-aurora {
  position: relative; width: 100%; max-width: 320px;
  border-radius: 18px; overflow: hidden;
  isolation: isolate;
}
.lf-aurora-bg {
  position: absolute; inset: -40%; z-index: 0;
  background:
    radial-gradient(40% 40% at 30% 30%, #7c6cff 0%, transparent 60%),
    radial-gradient(50% 50% at 70% 70%, #ff6c8a 0%, transparent 60%),
    radial-gradient(60% 60% at 50% 50%, #2eb88a 0%, transparent 60%);
  filter: blur(40px) saturate(140%);
  animation: lfaDrift 14s ease-in-out infinite alternate;
}
@keyframes lfaDrift {
  0%   { transform: translate3d(0, 0, 0) rotate(0deg); }
  100% { transform: translate3d(-8%, -4%, 0) rotate(8deg); }
}
.lf-aurora-card {
  position: relative; z-index: 1;
  background: rgba(15, 15, 19, 0.55);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 18px;
  padding: 28px 24px;
  display: flex; flex-direction: column; gap: 14px;
}
.lf-aurora-title { font-size: 18px; font-weight: 700; color: #f0eeff; }
.lf-aurora-sub   { font-size: 12px; color: #9d9bbf; margin-top: -10px; }
.lf-aurora-field { position: relative; display: block; }
.lf-aurora-field input {
  width: 100%; box-sizing: border-box;
  padding: 14px 12px 10px; font-size: 13px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 10px; color: #f0eeff;
  outline: none; transition: border-color .2s, background .2s;
}
.lf-aurora-field input:focus {
  border-color: #7c6cff;
  background: rgba(124,108,255,0.08);
}
.lf-aurora-field span {
  position: absolute; left: 12px; top: 12px;
  font-size: 12px; color: #9d9bbf; pointer-events: none;
  transition: transform .2s, color .2s, font-size .2s;
}
.lf-aurora-field input:focus + span,
.lf-aurora-field input:not(:placeholder-shown) + span {
  transform: translateY(-9px);
  font-size: 9px; color: #a78bfa; letter-spacing: 0.08em;
}
.lf-aurora-btn {
  margin-top: 4px; padding: 11px 14px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; font-size: 13px; font-weight: 600;
  border: none; border-radius: 10px; cursor: pointer;
  box-shadow: 0 6px 24px -8px rgba(124,108,255,0.7);
  transition: transform .15s, box-shadow .25s;
}
.lf-aurora-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 10px 32px -8px rgba(124,108,255,0.9);
}
.lf-aurora-foot { font-size: 11px; color: #9d9bbf; text-align: center; }
.lf-aurora-foot a { color: #a78bfa; text-decoration: none; }
<form class="lf-aurora">
  <div class="lf-aurora-bg"></div>
  <div class="lf-aurora-card">
    <div class="lf-aurora-title">Welcome back</div>
    <div class="lf-aurora-sub">Sign in to continue</div>
    <label class="lf-aurora-field">
      <input type="email" placeholder=" " required />
      <span>Email address</span>
    </label>
    <label class="lf-aurora-field">
      <input type="password" placeholder=" " required />
      <span>Password</span>
    </label>
    <button type="submit" class="lf-aurora-btn">Sign in →</button>
    <div class="lf-aurora-foot">No account? <a href="#">Create one</a></div>
  </div>
</form>
02 / 24
Neon Synthwave
Pure CSS
LOG IN
Neon login form in 80s-synthwave style. Hot-pink and cyan outline glows pulse around inputs and the submit button using stacked text-shadow.
.lf-neon {
  width: 100%; max-width: 280px;
  background: #0a0014;
  border: 1px solid rgba(255,108,255,0.35);
  border-radius: 14px;
  padding: 26px 22px;
  display: flex; flex-direction: column; gap: 14px;
  box-shadow: 0 0 40px rgba(255,108,255,0.15), inset 0 0 30px rgba(124,108,255,0.1);
}
.lf-neon-title {
  font-family: 'Courier New', monospace;
  font-size: 22px; font-weight: 700; text-align: center;
  color: #fff; letter-spacing: 0.3em;
  text-shadow:
    0 0 4px #fff,
    0 0 12px #ff6cff,
    0 0 24px #ff6cff;
}
.lf-neon-title span { color: #6cffff; text-shadow: 0 0 4px #fff, 0 0 12px #6cffff, 0 0 24px #6cffff; }
.lf-neon-input {
  background: transparent;
  border: 1px solid rgba(255,108,255,0.45);
  border-radius: 8px;
  padding: 11px 14px;
  font-family: 'Courier New', monospace;
  color: #fff; font-size: 12px;
  outline: none;
  transition: border-color .2s, box-shadow .2s;
}
.lf-neon-input::placeholder { color: rgba(255,108,255,0.55); }
.lf-neon-input:focus {
  border-color: #6cffff;
  box-shadow: 0 0 0 1px #6cffff, 0 0 16px rgba(108,255,255,0.4);
}
.lf-neon-btn {
  background: transparent;
  border: 1px solid #6cffff;
  border-radius: 8px;
  padding: 11px 14px;
  font-family: 'Courier New', monospace;
  font-size: 13px; font-weight: 700; letter-spacing: 0.25em;
  color: #6cffff; cursor: pointer;
  text-shadow: 0 0 6px #6cffff;
  box-shadow: inset 0 0 12px rgba(108,255,255,0.15), 0 0 14px rgba(108,255,255,0.3);
  animation: lfnPulse 1.6s ease-in-out infinite;
}
.lf-neon-btn:hover { color: #fff; background: rgba(108,255,255,0.1); }
@keyframes lfnPulse {
  0%, 100% { box-shadow: inset 0 0 12px rgba(108,255,255,0.15), 0 0 14px rgba(108,255,255,0.3); }
  50%      { box-shadow: inset 0 0 18px rgba(108,255,255,0.25), 0 0 28px rgba(108,255,255,0.55); }
}
<form class="lf-neon">
  <div class="lf-neon-title">LOG <span>IN</span></div>
  <input type="email" placeholder="[email protected]" required class="lf-neon-input" />
  <input type="password" placeholder="••••••••" required class="lf-neon-input" />
  <button type="submit" class="lf-neon-btn">ENTER</button>
</form>
03 / 24
Liquid Slide
Pure CSS
Account Login
Forgot?
Animated sign in form with a brand stripe that slides in on mount and underlined inputs that draw outward from the centre on focus.
.lf-liquid {
  position: relative; width: 100%; max-width: 320px;
  background: #15151d; border-radius: 14px; overflow: hidden;
  display: grid; grid-template-columns: 64px 1fr;
  border: 1px solid rgba(255,255,255,0.06);
}
.lf-liquid-stripe {
  background: linear-gradient(180deg, #7c6cff, #ff6c8a);
  animation: lfqSlide .6s cubic-bezier(.2,.9,.3,1.4) both;
  position: relative;
}
.lf-liquid-stripe::after {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 30%, rgba(255,255,255,0.45) 0%, transparent 40%);
  mix-blend-mode: screen;
}
@keyframes lfqSlide {
  from { transform: translateX(-100%); }
  to   { transform: translateX(0); }
}
.lf-liquid-body {
  padding: 22px 22px;
  display: flex; flex-direction: column; gap: 14px;
}
.lf-liquid-title {
  font-size: 16px; font-weight: 700; color: #f0eeff;
  letter-spacing: -0.01em;
}
.lf-liquid-row {
  position: relative;
}
.lf-liquid-row input {
  width: 100%; box-sizing: border-box;
  padding: 8px 0 9px; font-size: 13px;
  background: transparent; color: #f0eeff;
  border: none; border-bottom: 1px solid rgba(255,255,255,0.12);
  outline: none;
}
.lf-liquid-row::after {
  content: ''; position: absolute;
  bottom: 0; left: 50%; right: 50%; height: 1.5px;
  background: linear-gradient(90deg, #7c6cff, #ff6c8a);
  transition: left .28s ease, right .28s ease;
}
.lf-liquid-row:focus-within::after { left: 0; right: 0; }
.lf-liquid-row input::placeholder { color: #6b6987; }
.lf-liquid-meta {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 11px; color: #9d9bbf;
}
.lf-liquid-meta a { color: #a78bfa; text-decoration: none; }
.lf-liquid-meta input { accent-color: #7c6cff; margin-right: 4px; }
.lf-liquid-btn {
  margin-top: 4px; padding: 10px 14px;
  background: #f0eeff; color: #15151d;
  border: none; border-radius: 8px;
  font-size: 13px; font-weight: 700;
  cursor: pointer; transition: transform .12s;
}
.lf-liquid-btn:hover { transform: translateY(-1px); }
<form class="lf-liquid">
  <div class="lf-liquid-stripe"></div>
  <div class="lf-liquid-body">
    <div class="lf-liquid-title">Account Login</div>
    <div class="lf-liquid-row">
      <input type="email" placeholder="Email" required />
    </div>
    <div class="lf-liquid-row">
      <input type="password" placeholder="Password" required />
    </div>
    <div class="lf-liquid-meta">
      <label><input type="checkbox" /> Remember me</label>
      <a href="#">Forgot?</a>
    </div>
    <button type="submit" class="lf-liquid-btn">Continue</button>
  </div>
</form>
04 / 24
Card Flip Reset
Pure CSS
Sign in
Reset password
CSS-only flip card login form. The card rotates in 3D to reveal a "forgot password" form on the back — driven entirely by a hidden checkbox and sibling selectors, no JavaScript.
.lf-flip {
  width: 100%; max-width: 280px;
  perspective: 1200px;
}
.lf-flip-toggle { display: none; }
.lf-flip-stage {
  position: relative; width: 100%;
  transform-style: preserve-3d;
  transition: transform .7s cubic-bezier(.5,0,.3,1.2);
  min-height: 240px;
}
.lf-flip-toggle:checked ~ .lf-flip-stage {
  transform: rotateY(180deg);
}
.lf-flip-front,
.lf-flip-back {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; gap: 10px;
  padding: 24px 22px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 14px;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.lf-flip-back { transform: rotateY(180deg); }
.lf-flip-title { font-size: 16px; font-weight: 700; color: #f0eeff; margin-bottom: 2px; }
.lf-flip input {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px; padding: 10px 12px;
  color: #f0eeff; font-size: 13px; outline: none;
  transition: border-color .15s;
}
.lf-flip input:focus { border-color: #7c6cff; }
.lf-flip button {
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 8px;
  padding: 10px; font-size: 13px; font-weight: 600;
  cursor: pointer;
}
.lf-flip-link {
  font-size: 11px; color: #a78bfa; text-align: center;
  cursor: pointer; margin-top: 4px;
}
<div class="lf-flip">
  <input type="checkbox" id="lf-flip-toggle" class="lf-flip-toggle" />
  <div class="lf-flip-stage">
    <form class="lf-flip-front">
      <div class="lf-flip-title">Sign in</div>
      <input type="email" placeholder="Email" required />
      <input type="password" placeholder="Password" required />
      <button type="submit">Log in</button>
      <label for="lf-flip-toggle" class="lf-flip-link">Forgot password?</label>
    </form>
    <form class="lf-flip-back">
      <div class="lf-flip-title">Reset password</div>
      <input type="email" placeholder="Email to send reset link" required />
      <button type="submit">Send link</button>
      <label for="lf-flip-toggle" class="lf-flip-link">← Back to sign in</label>
    </form>
  </div>
</div>
05 / 24
Magic Link
Pure CSS
Sign in with magic link
We'll email you a one-time link. No password needed.
Magic-link / passwordless login form. A single email field with an animated wand-sparkle icon — the modern pattern for email-only authentication.
.lf-magic {
  width: 100%; max-width: 300px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 16px;
  padding: 28px 22px;
  display: flex; flex-direction: column; gap: 12px;
  align-items: center;
  text-align: center;
}
.lf-magic-icon {
  position: relative; width: 48px; height: 48px;
  margin-bottom: 4px;
}
.lf-magic-wand {
  position: absolute; inset: 12px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  border-radius: 50%;
  box-shadow: 0 0 24px rgba(124,108,255,0.55);
  animation: lfmFloat 3s ease-in-out infinite;
}
@keyframes lfmFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}
.lf-magic-spark {
  position: absolute; width: 4px; height: 4px;
  background: #fff; border-radius: 50%;
  box-shadow: 0 0 6px #fff;
  animation: lfmSpark 2s ease-in-out infinite;
}
.s1 { top: 4px;  left: 6px;  animation-delay: 0s; }
.s2 { top: 8px;  right: 4px; animation-delay: 0.5s; }
.s3 { bottom: 6px; left: 12px; animation-delay: 1s; }
@keyframes lfmSpark {
  0%, 100% { opacity: 0; transform: scale(0.4); }
  50%      { opacity: 1; transform: scale(1.2); }
}
.lf-magic-title { font-size: 15px; font-weight: 700; color: #f0eeff; }
.lf-magic-sub { font-size: 11px; color: #9d9bbf; line-height: 1.5; }
.lf-magic-input {
  width: 100%; box-sizing: border-box;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 10px;
  padding: 11px 14px; color: #f0eeff;
  font-size: 13px; outline: none;
  transition: border-color .2s, background .2s;
  text-align: center;
}
.lf-magic-input:focus { border-color: #7c6cff; background: rgba(124,108,255,0.08); }
.lf-magic-btn {
  width: 100%; padding: 11px 14px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 10px;
  font-size: 13px; font-weight: 600; cursor: pointer;
  box-shadow: 0 6px 24px -8px rgba(124,108,255,0.7);
}
<form class="lf-magic">
  <div class="lf-magic-icon">
    <span class="lf-magic-wand"></span>
    <span class="lf-magic-spark s1"></span>
    <span class="lf-magic-spark s2"></span>
    <span class="lf-magic-spark s3"></span>
  </div>
  <div class="lf-magic-title">Sign in with magic link</div>
  <div class="lf-magic-sub">We'll email you a one-time link. No password needed.</div>
  <input type="email" placeholder="[email protected]" required class="lf-magic-input" />
  <button type="submit" class="lf-magic-btn">Send magic link</button>
</form>
06 / 24
Terminal Prompt
Pure CSS
~/login
$ auth login
user:
pass:
Terminal-style login form. Monospace prompts, a blinking caret, and a green command-line submit — perfect for developer tools and CLI dashboards.
.lf-term {
  width: 100%; max-width: 320px;
  background: #0a0a0e;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px; overflow: hidden;
  font-family: 'JetBrains Mono', 'DM Mono', monospace;
  box-shadow: 0 18px 40px -12px rgba(0,0,0,0.6);
}
.lf-term-bar {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 12px;
  background: #15151d;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.lf-term-dot { width: 10px; height: 10px; border-radius: 50%; }
.lf-term-dot.r { background: #ff6c8a; }
.lf-term-dot.y { background: #f5b454; }
.lf-term-dot.g { background: #2eb88a; }
.lf-term-title {
  margin-left: auto; font-size: 11px; color: #6b6987; letter-spacing: 0.05em;
}
.lf-term-body {
  padding: 16px 14px;
  display: flex; flex-direction: column; gap: 10px;
  color: #a5f0c8;
  font-size: 13px;
}
.lf-term-line { display: flex; align-items: center; gap: 8px; }
.lf-term-prompt { color: #7c6cff; flex-shrink: 0; font-weight: 600; }
.lf-term-line input {
  flex: 1; background: transparent;
  border: none; outline: none;
  color: #fff; font-family: inherit; font-size: 13px;
  padding: 2px 0;
  caret-color: #2eb88a;
}
.lf-term-line input::placeholder { color: #4a4a5e; }
.lf-term-btn {
  align-self: flex-start; margin-top: 4px;
  padding: 6px 14px;
  background: rgba(46,184,138,0.08);
  border: 1px solid rgba(46,184,138,0.4);
  color: #2eb88a;
  font-family: inherit; font-size: 13px; font-weight: 600;
  cursor: pointer; border-radius: 5px;
}
.lf-term-btn:hover { background: rgba(46,184,138,0.18); }
.lf-term-caret {
  display: inline-block; margin-left: 2px;
  color: #2eb88a;
  animation: lftBlink 1s step-end infinite;
}
@keyframes lftBlink {
  50% { opacity: 0; }
}
<form class="lf-term">
  <div class="lf-term-bar">
    <span class="lf-term-dot r"></span>
    <span class="lf-term-dot y"></span>
    <span class="lf-term-dot g"></span>
    <span class="lf-term-title">~/login</span>
  </div>
  <div class="lf-term-body">
    <div class="lf-term-line"><span class="lf-term-prompt">$</span> auth login</div>
    <div class="lf-term-line">
      <span class="lf-term-prompt">user:</span>
      <input type="email" placeholder="[email protected]" required />
    </div>
    <div class="lf-term-line">
      <span class="lf-term-prompt">pass:</span>
      <input type="password" placeholder="••••••••" required />
    </div>
    <button type="submit" class="lf-term-btn">$ run<span class="lf-term-caret">_</span></button>
  </div>
</form>
07 / 24
Floating Pill
Pure CSS
Compact pill-shaped login form on a single line. Rotating brand avatar, inline email and password, and a circular submit arrow that pulses on hover.
.lf-pill {
  display: flex; align-items: center;
  gap: 6px;
  width: 100%; max-width: 320px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 100px;
  padding: 6px;
  box-shadow: 0 12px 32px -12px rgba(0,0,0,0.6);
}
.lf-pill-avatar {
  width: 38px; height: 38px;
  border-radius: 50%; flex-shrink: 0;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  padding: 2px;
  animation: lfpSpin 6s linear infinite;
}
.lf-pill-avatar-inner {
  width: 100%; height: 100%; border-radius: 50%;
  background: #15151d url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='38' height='38' viewBox='0 0 38 38'><circle cx='19' cy='15' r='5' fill='%23f0eeff'/><path d='M8 30c1.5-5 5.5-7 11-7s9.5 2 11 7' fill='%23f0eeff'/></svg>") center/cover;
}
@keyframes lfpSpin { to { transform: rotate(360deg); } }
.lf-pill-input {
  flex: 1; min-width: 0;
  background: transparent; border: none; outline: none;
  color: #f0eeff; font-size: 13px;
  padding: 8px 6px;
}
.lf-pill-input.pw { max-width: 90px; }
.lf-pill-input::placeholder { color: #6b6987; }
.lf-pill-btn {
  width: 38px; height: 38px; flex-shrink: 0;
  border: none; border-radius: 50%;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; font-size: 16px; font-weight: 700;
  cursor: pointer;
  box-shadow: 0 0 0 0 rgba(124,108,255,0.5);
  transition: box-shadow .25s, transform .15s;
}
.lf-pill-btn:hover {
  transform: scale(1.06);
  box-shadow: 0 0 0 6px rgba(124,108,255,0.18);
}
<form class="lf-pill">
  <div class="lf-pill-avatar">
    <div class="lf-pill-avatar-inner"></div>
  </div>
  <input type="email" placeholder="Email" class="lf-pill-input" required />
  <input type="password" placeholder="Password" class="lf-pill-input pw" required />
  <button type="submit" class="lf-pill-btn" aria-label="Sign in">→</button>
</form>
08 / 24
Gradient Border
Pure CSS
Welcome
Sign in to your workspace
Login form with an animated gradient border. A rotating conic-gradient frames a clean monochrome interior — a premium feel with one CSS property.
.lf-grad {
  position: relative;
  width: 100%; max-width: 320px;
  border-radius: 16px;
  padding: 1.5px;
  background: conic-gradient(from 0deg, #7c6cff, #ff6c8a, #2eb88a, #f5b454, #7c6cff);
  animation: lfgRotate 4s linear infinite;
}
@keyframes lfgRotate {
  to { --a: 360deg; transform: rotate(0); }
}
@property --a { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.lf-grad::before {
  content: ''; position: absolute; inset: -20px;
  background: inherit;
  filter: blur(24px); opacity: 0.5;
  z-index: -1; border-radius: inherit;
}
.lf-grad-inner {
  background: #15151d;
  border-radius: 14.5px;
  padding: 26px 24px;
  display: flex; flex-direction: column; gap: 12px;
}
.lf-grad-title { font-size: 18px; font-weight: 700; color: #f0eeff; }
.lf-grad-sub { font-size: 12px; color: #9d9bbf; margin-top: -8px; margin-bottom: 4px; }
.lf-grad-label {
  display: flex; flex-direction: column; gap: 5px;
  font-size: 11px; color: #9d9bbf;
  text-transform: uppercase; letter-spacing: 0.08em;
}
.lf-grad-label input {
  text-transform: none; letter-spacing: normal;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 10px 12px;
  color: #f0eeff; font-size: 13px;
  outline: none; transition: border-color .15s;
}
.lf-grad-label input:focus { border-color: #7c6cff; }
.lf-grad-btn {
  margin-top: 6px; padding: 11px;
  background: #f0eeff; color: #15151d;
  border: none; border-radius: 8px;
  font-size: 13px; font-weight: 700;
  cursor: pointer;
  transition: transform .12s;
}
.lf-grad-btn:hover { transform: translateY(-1px); }
<form class="lf-grad">
  <div class="lf-grad-inner">
    <div class="lf-grad-title">Welcome</div>
    <div class="lf-grad-sub">Sign in to your workspace</div>
    <label class="lf-grad-label">Email
      <input type="email" placeholder="[email protected]" required />
    </label>
    <label class="lf-grad-label">Password
      <input type="password" placeholder="At least 8 characters" required />
    </label>
    <button type="submit" class="lf-grad-btn">Sign in</button>
  </div>
</form>
09 / 24
Side Panel
Pure CSS
Sign in
Forgot your password?
Two-column SaaS login layout. A brand panel on the left with a subtle parallax shape, and a clean sign in form on the right — the classic dashboard pattern.
.lf-side {
  display: grid; grid-template-columns: 110px 1fr;
  width: 100%; max-width: 360px; min-height: 280px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 14px; overflow: hidden;
}
.lf-side-brand {
  position: relative; overflow: hidden;
  background: linear-gradient(160deg, #7c6cff 0%, #5b48d6 60%, #2a1f7a 100%);
  padding: 18px 14px;
  display: flex; flex-direction: column; justify-content: space-between;
  color: white;
}
.lf-side-shape {
  position: absolute; top: -30px; right: -30px;
  width: 120px; height: 120px; border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,0.25) 0%, transparent 60%);
  animation: lfsBlob 8s ease-in-out infinite alternate;
}
@keyframes lfsBlob {
  0%   { transform: translate(0, 0) scale(1); }
  100% { transform: translate(-10px, 12px) scale(1.15); }
}
.lf-side-logo {
  font-size: 20px; font-weight: 800; letter-spacing: 0.04em;
  background: rgba(255,255,255,0.18);
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 8px; backdrop-filter: blur(8px);
}
.lf-side-tag { font-size: 11px; line-height: 1.5; opacity: 0.92; }
.lf-side-form {
  padding: 24px 22px;
  display: flex; flex-direction: column; gap: 10px;
}
.lf-side-title { font-size: 16px; font-weight: 700; color: #f0eeff; margin-bottom: 4px; }
.lf-side-form input {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 9px 12px;
  color: #f0eeff; font-size: 13px; outline: none;
  transition: border-color .15s;
}
.lf-side-form input:focus { border-color: #7c6cff; }
.lf-side-form button {
  margin-top: 4px; padding: 10px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 8px;
  font-size: 13px; font-weight: 600; cursor: pointer;
}
.lf-side-foot { font-size: 11px; color: #a78bfa; text-decoration: none; text-align: center; margin-top: 2px; }
<form class="lf-side">
  <aside class="lf-side-brand">
    <div class="lf-side-shape"></div>
    <div class="lf-side-logo">CF</div>
    <div class="lf-side-tag">Build the front-end<br/>you've been imagining.</div>
  </aside>
  <div class="lf-side-form">
    <div class="lf-side-title">Sign in</div>
    <input type="email" placeholder="Work email" required />
    <input type="password" placeholder="Password" required />
    <button type="submit">Continue →</button>
    <a href="#" class="lf-side-foot">Forgot your password?</a>
  </div>
</form>
10 / 24
Social First
Pure CSS
Sign in
or
By continuing you agree to our Terms
Social-first sign in form with OAuth buttons (Google, GitHub) up top, a divider, and a compact email fallback — the standard product onboarding pattern.
.lf-soc {
  width: 100%; max-width: 290px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 14px;
  padding: 26px 22px;
  display: flex; flex-direction: column; gap: 10px;
}
.lf-soc-title {
  font-size: 16px; font-weight: 700; color: #f0eeff;
  text-align: center; margin-bottom: 4px;
}
.lf-soc-btn {
  display: flex; align-items: center; gap: 10px;
  justify-content: center;
  padding: 9px 14px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  color: #f0eeff; font-size: 13px; font-weight: 500;
  cursor: pointer;
  transition: background .15s, transform .15s;
}
.lf-soc-btn:hover { background: rgba(255,255,255,0.08); transform: translateY(-1px); }
.lf-soc-ic {
  width: 18px; height: 18px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; font-weight: 800; font-size: 11px;
  background: white; color: #15151d;
}
.lf-soc-btn.github .lf-soc-ic { background: #f0eeff; color: #15151d; }
.lf-soc-or {
  display: flex; align-items: center; gap: 10px;
  margin: 6px 0;
  font-size: 11px; color: #6b6987;
  text-transform: uppercase; letter-spacing: 0.1em;
}
.lf-soc-or::before, .lf-soc-or::after {
  content: ''; flex: 1; height: 1px;
  background: rgba(255,255,255,0.08);
}
.lf-soc input {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 10px 12px;
  color: #f0eeff; font-size: 13px; outline: none;
}
.lf-soc input:focus { border-color: #7c6cff; }
.lf-soc-submit {
  padding: 10px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 8px;
  font-size: 13px; font-weight: 600; cursor: pointer;
}
.lf-soc-foot {
  font-size: 10px; color: #6b6987;
  text-align: center; margin-top: 4px;
}
.lf-soc-foot a { color: #a78bfa; text-decoration: none; }
<form class="lf-soc">
  <div class="lf-soc-title">Sign in</div>
  <button type="button" class="lf-soc-btn google">
    <span class="lf-soc-ic">G</span> Continue with Google
  </button>
  <button type="button" class="lf-soc-btn github">
    <span class="lf-soc-ic">●</span> Continue with GitHub
  </button>
  <div class="lf-soc-or"><span>or</span></div>
  <input type="email" placeholder="Email address" required />
  <button type="submit" class="lf-soc-submit">Continue with email</button>
  <div class="lf-soc-foot">By continuing you agree to our <a href="#">Terms</a></div>
</form>
11 / 24
Animated Mascot
Pure CSS
Playful login form with an animated mascot. A CSS-drawn face whose eyes follow the focused input via `:has()` — left for email, down for password — and blinks on idle.
.lf-mascot {
  width: 100%; max-width: 280px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 16px;
  padding: 24px 22px 22px;
  display: flex; flex-direction: column; gap: 10px;
  align-items: center;
}
.lf-mascot-face {
  width: 78px; height: 78px;
  border-radius: 50%;
  background: linear-gradient(135deg, #fde68a, #fbbf24);
  position: relative;
  margin-bottom: 8px;
  box-shadow: 0 8px 24px -8px rgba(251,191,36,0.6);
}
.lf-mascot-eye {
  position: absolute; top: 28px;
  width: 14px; height: 14px;
  background: #15151d; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.lf-mascot-eye.l { left: 18px; }
.lf-mascot-eye.r { right: 18px; }
.lf-mascot-pupil {
  width: 5px; height: 5px;
  background: white; border-radius: 50%;
  transition: transform .25s ease;
  animation: lfmBlink 4s ease-in-out infinite;
}
@keyframes lfmBlink {
  0%, 92%, 100% { transform: scaleY(1); }
  95%           { transform: scaleY(0.1); }
}
.lf-mascot-mouth {
  position: absolute; bottom: 20px; left: 50%;
  width: 22px; height: 12px;
  border: 2.5px solid #15151d;
  border-top: none; border-radius: 0 0 22px 22px;
  transform: translateX(-50%);
}
/* Eyes track focused input */
.lf-mascot:has(.email:focus) .lf-mascot-pupil { transform: translate(-3px, 0); }
.lf-mascot:has(.pwd:focus)   .lf-mascot-pupil { transform: translate(0, 3px); }
.lf-mascot:has(.lf-mascot-btn:hover) .lf-mascot-mouth {
  height: 18px; border-radius: 0 0 28px 28px;
}
.lf-mascot-input {
  width: 100%; box-sizing: border-box;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 10px;
  padding: 10px 14px;
  color: #f0eeff; font-size: 13px; outline: none;
  transition: border-color .15s;
}
.lf-mascot-input:focus { border-color: #fbbf24; }
.lf-mascot-btn {
  width: 100%; padding: 10px;
  background: linear-gradient(135deg, #fbbf24, #ef4444);
  color: white; border: none; border-radius: 10px;
  font-size: 13px; font-weight: 700; cursor: pointer;
  margin-top: 4px;
  transition: transform .12s;
}
.lf-mascot-btn:hover { transform: translateY(-1px); }
<form class="lf-mascot">
  <div class="lf-mascot-face">
    <div class="lf-mascot-eye l"><div class="lf-mascot-pupil"></div></div>
    <div class="lf-mascot-eye r"><div class="lf-mascot-pupil"></div></div>
    <div class="lf-mascot-mouth"></div>
  </div>
  <input type="email" placeholder="Email" required class="lf-mascot-input email" />
  <input type="password" placeholder="Password" required class="lf-mascot-input pwd" />
  <button type="submit" class="lf-mascot-btn">Hop in!</button>
</form>
12 / 24
Compact Modal
Pure CSS
Sign in to Codefronts
Use your email and password to continue
Modal / dialog login form. Dense and professional, with subtle hover glow on inputs and a primary action that fills with brand colour on hover.
.lf-modal {
  position: relative;
  width: 100%; max-width: 320px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 12px;
  padding: 24px 22px 22px;
  display: flex; flex-direction: column; gap: 12px;
  box-shadow: 0 24px 48px -16px rgba(0,0,0,0.7), 0 0 0 1px rgba(255,255,255,0.04);
}
.lf-modal-close {
  position: absolute; top: 12px; right: 12px;
  width: 22px; height: 22px;
  background: transparent; border: none;
  color: #6b6987; font-size: 18px; cursor: pointer;
  border-radius: 4px; transition: background .15s, color .15s;
  line-height: 1;
}
.lf-modal-close:hover { background: rgba(255,255,255,0.06); color: #f0eeff; }
.lf-modal-title { font-size: 16px; font-weight: 700; color: #f0eeff; }
.lf-modal-sub { font-size: 12px; color: #9d9bbf; margin-top: -8px; margin-bottom: 4px; }
.lf-modal-row {
  display: flex; flex-direction: column; gap: 5px;
  font-size: 11px; color: #9d9bbf;
}
.lf-modal-row > span {
  display: flex; justify-content: space-between; align-items: center;
}
.lf-modal-row > span a { color: #a78bfa; text-decoration: none; font-size: 11px; }
.lf-modal-row input {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 10px 12px;
  color: #f0eeff; font-size: 13px; outline: none;
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.lf-modal-row input:hover { background: rgba(255,255,255,0.06); }
.lf-modal-row input:focus {
  border-color: #7c6cff;
  box-shadow: 0 0 0 3px rgba(124,108,255,0.15);
}
.lf-modal-check {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; color: #9d9bbf;
}
.lf-modal-check input { accent-color: #7c6cff; }
.lf-modal-submit {
  padding: 10px;
  background: rgba(124,108,255,0.18);
  color: #c8c0ff;
  border: 1px solid rgba(124,108,255,0.4);
  border-radius: 8px;
  font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background .2s, color .2s, border-color .2s;
}
.lf-modal-submit:hover {
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white;
  border-color: transparent;
}
<form class="lf-modal">
  <button type="button" class="lf-modal-close" aria-label="Close">×</button>
  <div class="lf-modal-title">Sign in to Codefronts</div>
  <div class="lf-modal-sub">Use your email and password to continue</div>
  <label class="lf-modal-row">
    <span>Email</span>
    <input type="email" placeholder="[email protected]" required />
  </label>
  <label class="lf-modal-row">
    <span>Password <a href="#">Forgot?</a></span>
    <input type="password" placeholder="••••••••" required />
  </label>
  <label class="lf-modal-check">
    <input type="checkbox" /> Keep me signed in for 30 days
  </label>
  <button type="submit" class="lf-modal-submit">Sign in</button>
</form>
13 / 24
Glass Frosted
Pure CSS

Sign in

Welcome back. Continue where you left off.

Frosted-glass login form on a soft photographic background. Translucent inputs with subtle inner highlights — a calm, premium hero treatment.
.lf-glass {
  position: relative; isolation: isolate;
  width: 100%; max-width: 320px;
  border-radius: 18px; overflow: hidden;
}
.lf-glass-bg {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(40% 50% at 20% 30%, #f59e0b 0%, transparent 60%),
    radial-gradient(50% 60% at 80% 70%, #7c3aed 0%, transparent 60%),
    radial-gradient(60% 70% at 50% 50%, #ef4444 0%, transparent 60%),
    #0a0a14;
  filter: blur(30px) saturate(120%);
  transform: scale(1.2);
}
.lf-glass-card {
  position: relative; z-index: 1;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.18);
  backdrop-filter: blur(24px) saturate(140%);
  -webkit-backdrop-filter: blur(24px) saturate(140%);
  border-radius: 18px;
  padding: 26px 22px;
  display: grid; gap: 14px;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.25),
    0 18px 48px -16px rgba(0,0,0,0.5);
}
.lf-glass-card header { display: grid; gap: 4px; }
.lf-glass-title { margin: 0; font-size: 17px; font-weight: 700; color: #fff; }
.lf-glass-sub { margin: 0; font-size: 12px; color: rgba(255,255,255,0.7); line-height: 1.5; }
.lf-glass-field { display: grid; gap: 5px; font-size: 11px; color: rgba(255,255,255,0.7); }
.lf-glass-field input {
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 10px;
  padding: 10px 12px; font-size: 13px;
  color: #fff; outline: none;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.15);
  transition: border-color .2s, background .2s;
}
.lf-glass-field input::placeholder { color: rgba(255,255,255,0.45); }
.lf-glass-field input:focus {
  border-color: rgba(255,255,255,0.45);
  background: rgba(255,255,255,0.14);
}
.lf-glass-btn {
  margin-top: 4px; padding: 11px;
  background: rgba(255,255,255,0.92);
  color: #15151d;
  border: 1px solid rgba(255,255,255,0.5);
  border-radius: 10px;
  font-size: 13px; font-weight: 700;
  cursor: pointer;
  transition: transform .12s, background .15s;
}
.lf-glass-btn:hover { transform: translateY(-1px); background: #fff; }
<form class="lf-glass" aria-label="Sign in form">
  <div class="lf-glass-bg" aria-hidden="true"></div>
  <article class="lf-glass-card">
    <header>
      <h2 class="lf-glass-title">Sign in</h2>
      <p class="lf-glass-sub">Welcome back. Continue where you left off.</p>
    </header>
    <label class="lf-glass-field">
      <span>Email</span>
      <input type="email" name="email" autocomplete="email" placeholder="[email protected]" required />
    </label>
    <label class="lf-glass-field">
      <span>Password</span>
      <input type="password" name="password" autocomplete="current-password" placeholder="••••••••" required />
    </label>
    <button type="submit" class="lf-glass-btn">Continue</button>
  </article>
</form>
14 / 24
Step-by-Step
Pure CSS
1 of 2
What's your email?
Now your password
Multi-step login form. Enter email, then password — the card slides between steps with a progress bar, driven entirely by `:has()` and `:checked`. No JavaScript.
.lf-step {
  width: 100%; max-width: 320px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 14px;
  padding: 22px 22px;
  display: grid; gap: 14px;
  overflow: hidden;
}
.lf-step-radio { position: absolute; opacity: 0; pointer-events: none; }
.lf-step-head {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 12px;
  font-size: 11px; color: #9d9bbf;
}
.lf-step-bar {
  height: 3px; border-radius: 99px;
  background: rgba(255,255,255,0.06);
  position: relative; overflow: hidden;
}
.lf-step-bar::after {
  content: ''; position: absolute; inset: 0; right: 50%;
  background: linear-gradient(90deg, #7c6cff, #ff6c8a);
  border-radius: inherit;
  transition: right .4s ease;
}
.lf-step:has(#lf-step-2:checked) .lf-step-bar::after { right: 0; }
.lf-step:has(#lf-step-2:checked) .lf-step-now::after { content: '2'; }
.lf-step-now { font-weight: 700; color: #f0eeff; }
.lf-step-now::after { content: '1'; }
.lf-step-now { font-size: 0; }
.lf-step-now::after { font-size: 11px; }
.lf-step-track {
  display: grid; grid-template-columns: 100% 100%;
  width: 100%;
  transition: transform .4s cubic-bezier(.6,0,.2,1);
}
.lf-step:has(#lf-step-2:checked) .lf-step-track { transform: translateX(-100%); }
.lf-step-pane {
  border: 0; padding: 0; margin: 0;
  display: grid; gap: 12px;
  min-width: 0;
}
.lf-step-label {
  font-size: 13px; font-weight: 600; color: #f0eeff;
  padding: 0;
}
.lf-step-row input {
  width: 100%; box-sizing: border-box;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 10px 12px; font-size: 13px;
  color: #f0eeff; outline: none;
  transition: border-color .15s;
}
.lf-step-row input:focus { border-color: #7c6cff; }
.lf-step-actions { display: grid; grid-template-columns: auto 1fr; gap: 8px; }
.lf-step-btn {
  padding: 10px 14px; border-radius: 8px;
  font-size: 13px; font-weight: 600;
  cursor: pointer; text-align: center;
  border: 1px solid transparent;
  transition: transform .12s, background .15s;
}
.lf-step-btn.primary {
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white;
}
.lf-step-btn.primary:hover { transform: translateY(-1px); }
.lf-step-btn.ghost {
  background: transparent;
  color: #9d9bbf;
  border-color: rgba(255,255,255,0.1);
}
.lf-step-btn.ghost:hover { color: #f0eeff; background: rgba(255,255,255,0.04); }
<form class="lf-step" aria-label="Two-step sign in">
  <input type="radio" id="lf-step-1" name="lf-step" class="lf-step-radio" checked />
  <input type="radio" id="lf-step-2" name="lf-step" class="lf-step-radio" />

  <header class="lf-step-head">
    <span class="lf-step-bar" aria-hidden="true"></span>
    <span class="lf-step-counter"><span class="lf-step-now">1</span> of 2</span>
  </header>

  <div class="lf-step-track">
    <fieldset class="lf-step-pane">
      <legend class="lf-step-label">What's your email?</legend>
      <label class="lf-step-row">
        <input type="email" name="email" autocomplete="email" placeholder="[email protected]" required />
      </label>
      <label for="lf-step-2" class="lf-step-btn primary">Next →</label>
    </fieldset>

    <fieldset class="lf-step-pane">
      <legend class="lf-step-label">Now your password</legend>
      <label class="lf-step-row">
        <input type="password" name="password" autocomplete="current-password" placeholder="••••••••" required />
      </label>
      <div class="lf-step-actions">
        <label for="lf-step-1" class="lf-step-btn ghost">← Back</label>
        <button type="submit" class="lf-step-btn primary">Sign in</button>
      </div>
    </fieldset>
  </div>
</form>
15 / 24
Animated Gradient Border
Pure CSS

Sign in

A small bit of magic, every time.

Animated rainbow gradient border login form. A `@property`-driven conic gradient genuinely rotates around the card edge — true property animation, not a keyframes hack.
@property --lf-prop-angle {
  syntax: '<angle>'; inherits: false; initial-value: 0deg;
}
.lf-prop {
  position: relative;
  width: 100%; max-width: 320px;
  border-radius: 16px;
  padding: 1.5px;
  background: conic-gradient(
    from var(--lf-prop-angle, 0deg),
    #7c6cff, #ff6c8a, #2eb88a, #f5b454, #7c6cff
  );
  animation: lfPropSpin 5s linear infinite;
}
@keyframes lfPropSpin {
  to { --lf-prop-angle: 360deg; }
}
.lf-prop::before {
  content: ''; position: absolute; inset: -22px; z-index: -1;
  background: inherit; filter: blur(28px); opacity: 0.45;
  border-radius: inherit;
}
.lf-prop-inner {
  background: #15151d;
  border-radius: 14.5px;
  padding: 24px 22px;
  display: grid; gap: 12px;
}
.lf-prop-title { margin: 0; font-size: 17px; font-weight: 700; color: #f0eeff; }
.lf-prop-sub { margin: -6px 0 4px; font-size: 12px; color: #9d9bbf; }
.lf-prop-field { display: grid; gap: 5px; font-size: 11px; color: #9d9bbf; }
.lf-prop-field input {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 10px 12px; font-size: 13px;
  color: #f0eeff; outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.lf-prop-field input:focus {
  border-color: #7c6cff;
  box-shadow: 0 0 0 3px rgba(124,108,255,0.15);
}
.lf-prop-btn {
  margin-top: 4px; padding: 11px;
  background: #f0eeff; color: #15151d;
  border: none; border-radius: 8px;
  font-size: 13px; font-weight: 700;
  cursor: pointer;
  transition: transform .12s;
}
.lf-prop-btn:hover { transform: translateY(-1px); }
<form class="lf-prop" aria-label="Animated gradient sign in">
  <div class="lf-prop-inner">
    <h2 class="lf-prop-title">Sign in</h2>
    <p class="lf-prop-sub">A small bit of magic, every time.</p>
    <label class="lf-prop-field">
      <span>Email</span>
      <input type="email" name="email" autocomplete="email" placeholder="[email protected]" required />
    </label>
    <label class="lf-prop-field">
      <span>Password</span>
      <input type="password" name="password" autocomplete="current-password" placeholder="••••••••" required />
    </label>
    <button type="submit" class="lf-prop-btn">Sign in</button>
  </div>
</form>
16 / 24
Vault Lock
Pure CSS

Vault access

Authenticate to view encrypted contents

Vault-style secure login form. The lock dial rotates and the bolt slides open the moment the password field gains focus — pure CSS, driven by `:focus-within` and `:has()`.
.lf-vault {
  width: 100%; max-width: 300px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 16px;
  padding: 26px 22px 22px;
  display: grid; gap: 10px; justify-items: center;
  text-align: center;
}
.lf-vault-lock {
  position: relative; margin: 0 0 6px;
  width: 60px; height: 60px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #2a2a36 0%, #15151d 70%);
  border: 2px solid #2eb88a;
  box-shadow: 0 0 0 4px rgba(46,184,138,0.08), 0 0 24px rgba(46,184,138,0.25);
  transition: border-color .3s, box-shadow .3s;
}
.lf-vault-dial {
  position: absolute; top: 50%; left: 50%;
  width: 26px; height: 3px;
  background: #2eb88a; border-radius: 2px;
  transform: translate(-50%, -50%) rotate(35deg);
  transform-origin: center;
  transition: transform .5s cubic-bezier(.5,0,.3,1.3), background .3s;
}
.lf-vault-dial::after {
  content: ''; position: absolute; inset: -3px auto -3px -3px;
  width: 9px; border-radius: 50%;
  background: #2eb88a;
  transition: background .3s;
}
.lf-vault-bolt {
  position: absolute; bottom: -8px; left: 50%;
  width: 14px; height: 18px;
  background: #2eb88a; border-radius: 3px;
  transform: translateX(-50%) translateY(0);
  transition: transform .35s ease, background .3s;
}
.lf-vault:has(.lf-vault-pw input:focus) .lf-vault-lock {
  border-color: #7c6cff;
  box-shadow: 0 0 0 4px rgba(124,108,255,0.12), 0 0 28px rgba(124,108,255,0.45);
}
.lf-vault:has(.lf-vault-pw input:focus) .lf-vault-dial {
  transform: translate(-50%, -50%) rotate(220deg);
  background: #7c6cff;
}
.lf-vault:has(.lf-vault-pw input:focus) .lf-vault-dial::after { background: #7c6cff; }
.lf-vault:has(.lf-vault-pw input:focus) .lf-vault-bolt {
  transform: translateX(-50%) translateY(8px);
  background: #7c6cff;
}
.lf-vault-title { margin: 0; font-size: 15px; font-weight: 700; color: #f0eeff; }
.lf-vault-sub { margin: 0 0 4px; font-size: 11px; color: #9d9bbf; }
.lf-vault-field { display: grid; gap: 4px; font-size: 11px; color: #9d9bbf; width: 100%; text-align: left; }
.lf-vault-field input {
  width: 100%; box-sizing: border-box;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 10px 12px; font-size: 13px;
  color: #f0eeff; outline: none;
  transition: border-color .15s;
}
.lf-vault-field input:focus { border-color: #7c6cff; }
.lf-vault-btn {
  width: 100%; padding: 11px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 8px;
  font-size: 13px; font-weight: 700; cursor: pointer;
  transition: transform .12s;
}
.lf-vault-btn:hover { transform: translateY(-1px); }
<form class="lf-vault" aria-label="Vault sign in">
  <figure class="lf-vault-lock" aria-hidden="true">
    <span class="lf-vault-dial"></span>
    <span class="lf-vault-bolt"></span>
  </figure>
  <h2 class="lf-vault-title">Vault access</h2>
  <p class="lf-vault-sub">Authenticate to view encrypted contents</p>
  <label class="lf-vault-field">
    <span>Email</span>
    <input type="email" name="email" autocomplete="email" placeholder="[email protected]" required />
  </label>
  <label class="lf-vault-field lf-vault-pw">
    <span>Master password</span>
    <input type="password" name="password" autocomplete="current-password" placeholder="••••••••" required />
  </label>
  <button type="submit" class="lf-vault-btn">Unlock</button>
</form>
17 / 24
Brutalist Stamp
Pure CSS

Sign in.

No frills. Get back to work.

Brutalist login form with heavy borders, hard-edge offset shadow, and a stamp-style badge. A confident no-nonsense look for portfolios, dev tools, and editorial brands.
.lf-brut {
  position: relative;
  width: 100%; max-width: 320px;
  background: #fef9c3;
  border: 2.5px solid #15151d;
  border-radius: 6px;
  padding: 22px 20px;
  display: grid; gap: 12px;
  box-shadow: 6px 6px 0 0 #15151d;
  font-family: 'JetBrains Mono', 'DM Mono', monospace;
}
.lf-brut-stamp {
  position: absolute; top: -14px; right: 12px;
  background: #ef4444; color: #fef9c3;
  border: 2px solid #15151d;
  padding: 2px 10px;
  font-size: 10px; font-weight: 800;
  letter-spacing: 0.18em;
  display: inline-flex; gap: 6px;
  transform: rotate(2deg);
  box-shadow: 3px 3px 0 #15151d;
}
.lf-brut-title { margin: 0; font-size: 22px; font-weight: 800; color: #15151d; letter-spacing: -0.02em; }
.lf-brut-sub   { margin: -6px 0 4px; font-size: 12px; color: #4a4a5e; }
.lf-brut-row {
  display: grid; gap: 4px;
  font-size: 10px; font-weight: 800; letter-spacing: 0.14em;
  color: #15151d;
}
.lf-brut-row input {
  background: #fff;
  border: 2px solid #15151d;
  border-radius: 4px;
  padding: 9px 12px;
  font-size: 13px; font-family: inherit;
  color: #15151d; outline: none;
  transition: box-shadow .15s, transform .12s;
}
.lf-brut-row input:focus {
  box-shadow: 4px 4px 0 #15151d;
  transform: translate(-2px, -2px);
}
.lf-brut-btn {
  background: #15151d; color: #fef9c3;
  border: 2px solid #15151d;
  border-radius: 4px;
  padding: 11px; font-family: inherit;
  font-size: 13px; font-weight: 800; letter-spacing: 0.14em;
  cursor: pointer;
  transition: transform .12s, box-shadow .15s, background .15s, color .15s;
}
.lf-brut-btn:hover {
  background: #ef4444; color: #fef9c3;
  transform: translate(-2px, -2px);
  box-shadow: 4px 4px 0 #15151d;
}
<form class="lf-brut" aria-label="Brutalist sign in">
  <span class="lf-brut-stamp" aria-hidden="true">
    <span>SECURE</span>
    <span>·  AUTH  ·</span>
    <span>2025</span>
  </span>
  <h2 class="lf-brut-title">Sign in.</h2>
  <p class="lf-brut-sub">No frills. Get back to work.</p>
  <label class="lf-brut-row">
    <span>EMAIL</span>
    <input type="email" name="email" autocomplete="email" placeholder="[email protected]" required />
  </label>
  <label class="lf-brut-row">
    <span>PASSWORD</span>
    <input type="password" name="password" autocomplete="current-password" placeholder="••••••••" required />
  </label>
  <button type="submit" class="lf-brut-btn">▸ ENTER</button>
</form>
18 / 24
Show Password Toggle
Light JS

Sign in

Forgot password?
Login form with a show / hide password toggle. Inline eye-icon button with proper `aria-pressed` and `aria-label` handling for accessibility.
.lf-show {
  width: 100%; max-width: 320px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 14px;
  padding: 26px 24px;
  display: grid; gap: 12px;
}
.lf-show-title { margin: 0; font-size: 17px; font-weight: 700; color: #f0eeff; }
.lf-show-row { display: grid; gap: 5px; font-size: 11px; color: #9d9bbf; }
.lf-show-row input {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 10px 12px; font-size: 13px;
  color: #f0eeff; outline: none;
  transition: border-color .15s;
}
.lf-show-row input:focus { border-color: #7c6cff; }
.lf-show-pw { position: relative; display: block; }
.lf-show-pw input { width: 100%; box-sizing: border-box; padding-right: 38px; }
.lf-show-eye {
  position: absolute; right: 6px; top: 50%;
  transform: translateY(-50%);
  width: 28px; height: 28px;
  display: grid; place-items: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  color: #9d9bbf; cursor: pointer;
  transition: color .15s, background .15s, border-color .15s;
}
.lf-show-eye:hover { color: #f0eeff; background: rgba(255,255,255,0.04); }
.lf-show-eye[aria-pressed="true"] { color: #7c6cff; border-color: rgba(124,108,255,0.4); background: rgba(124,108,255,0.08); }
.lf-show-meta {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 11px; color: #9d9bbf;
}
.lf-show-meta input { accent-color: #7c6cff; margin-right: 4px; }
.lf-show-meta a { color: #a78bfa; text-decoration: none; }
.lf-show-submit {
  margin-top: 4px; padding: 11px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 8px;
  font-size: 13px; font-weight: 600; cursor: pointer;
  transition: transform .12s;
}
.lf-show-submit:hover { transform: translateY(-1px); }

/* ─── tiny JS to toggle reveal ─── */
/*
document.querySelectorAll('[data-lf-eye]').forEach(btn => {
  btn.addEventListener('click', () => {
    const input = btn.previousElementSibling;
    const next  = input.type === 'password' ? 'text' : 'password';
    input.type = next;
    btn.setAttribute('aria-pressed', String(next === 'text'));
    btn.setAttribute('aria-label', next === 'text' ? 'Hide password' : 'Show password');
  });
});
*/
<form class="lf-show" aria-label="Sign in with password reveal">
  <h2 class="lf-show-title">Sign in</h2>
  <label class="lf-show-row">
    <span>Email</span>
    <input type="email" name="email" autocomplete="email" placeholder="[email protected]" required />
  </label>
  <label class="lf-show-row lf-show-row-pw">
    <span>Password</span>
    <span class="lf-show-pw">
      <input type="password" name="password" autocomplete="current-password" placeholder="••••••••" required />
      <button type="button" class="lf-show-eye" aria-label="Show password" aria-pressed="false" data-lf-eye>
        <svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true">
          <path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
                d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z M12 9a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"/>
        </svg>
      </button>
    </span>
  </label>
  <div class="lf-show-meta">
    <label><input type="checkbox" name="remember" /> Remember me</label>
    <a href="#">Forgot password?</a>
  </div>
  <button type="submit" class="lf-show-submit">Sign in</button>
</form>
19 / 24
OTP Verify
Light JS

Enter code

We sent a 6-digit code to [email protected]

Verification code

Didn't get it? Resend code

OTP / one-time-passcode login form. Six digit boxes with auto-advance, backspace step-back, paste-to-fill, and `autocomplete="one-time-code"` for SMS auto-suggest.
.lf-otp {
  width: 100%; max-width: 320px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 14px;
  padding: 26px 22px;
  display: grid; gap: 12px;
  text-align: center;
}
.lf-otp-title { margin: 0; font-size: 16px; font-weight: 700; color: #f0eeff; }
.lf-otp-sub   { margin: -4px 0 6px; font-size: 12px; color: #9d9bbf; line-height: 1.5; }
.lf-otp-sub strong { color: #f0eeff; font-weight: 600; }
.lf-otp-row {
  border: 0; padding: 0; margin: 4px 0;
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px;
}
.lf-otp-legend {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.lf-otp-row input {
  width: 100%; box-sizing: border-box;
  aspect-ratio: 1 / 1;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  font-size: 18px; font-weight: 700;
  text-align: center;
  color: #f0eeff; outline: none;
  caret-color: #7c6cff;
  transition: border-color .15s, background .15s, transform .12s;
}
.lf-otp-row input:focus {
  border-color: #7c6cff;
  background: rgba(124,108,255,0.08);
  transform: translateY(-1px);
}
.lf-otp-btn {
  margin-top: 4px; padding: 11px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 8px;
  font-size: 13px; font-weight: 600; cursor: pointer;
}
.lf-otp-foot { margin: 0; font-size: 11px; color: #9d9bbf; }
.lf-otp-foot a { color: #a78bfa; text-decoration: none; }

/* ─── tiny JS to auto-advance & step back ─── */
/*
document.querySelectorAll('[data-lf-otp]').forEach((input, i, all) => {
  input.addEventListener('input', () => {
    input.value = input.value.replace(/\D/g, '').slice(0, 1);
    if (input.value && all[i + 1]) all[i + 1].focus();
  });
  input.addEventListener('keydown', e => {
    if (e.key === 'Backspace' && !input.value && all[i - 1]) all[i - 1].focus();
  });
});
*/
<form class="lf-otp" aria-label="One-time passcode entry">
  <h2 class="lf-otp-title">Enter code</h2>
  <p class="lf-otp-sub">We sent a 6-digit code to <strong>[email protected]</strong></p>
  <fieldset class="lf-otp-row">
    <legend class="lf-otp-legend">Verification code</legend>
    <input type="text" inputmode="numeric" maxlength="1" autocomplete="one-time-code" pattern="[0-9]" aria-label="Digit 1" data-lf-otp />
    <input type="text" inputmode="numeric" maxlength="1" pattern="[0-9]" aria-label="Digit 2" data-lf-otp />
    <input type="text" inputmode="numeric" maxlength="1" pattern="[0-9]" aria-label="Digit 3" data-lf-otp />
    <input type="text" inputmode="numeric" maxlength="1" pattern="[0-9]" aria-label="Digit 4" data-lf-otp />
    <input type="text" inputmode="numeric" maxlength="1" pattern="[0-9]" aria-label="Digit 5" data-lf-otp />
    <input type="text" inputmode="numeric" maxlength="1" pattern="[0-9]" aria-label="Digit 6" data-lf-otp />
  </fieldset>
  <button type="submit" class="lf-otp-btn">Verify &amp; sign in</button>
  <p class="lf-otp-foot">Didn't get it? <a href="#">Resend code</a></p>
</form>
20 / 24
Strength Meter
Pure CSS

Create account

Sign-up form with a live password strength meter. The bar grows red → amber → green as the password gets stronger — driven entirely by `:has()` and `:valid`, no JavaScript scoring.
.lf-str {
  width: 100%; max-width: 320px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 14px;
  padding: 24px 22px;
  display: grid; gap: 12px;
}
.lf-str-title { margin: 0; font-size: 17px; font-weight: 700; color: #f0eeff; }
.lf-str-row { display: grid; gap: 6px; font-size: 11px; color: #9d9bbf; }
.lf-str-row > input {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 10px 12px; font-size: 13px;
  color: #f0eeff; outline: none;
  transition: border-color .15s;
}
.lf-str-row > input:focus { border-color: #7c6cff; }
.lf-str-meter {
  position: relative;
  height: 4px; border-radius: 99px;
  background: rgba(255,255,255,0.06);
  overflow: hidden;
}
.lf-str-fill {
  position: absolute; inset: 0;
  width: 0;
  background: linear-gradient(90deg, #ef4444, #f5b454, #2eb88a);
  border-radius: inherit;
  transition: width .3s ease;
}
/* CSS-only strength: width is driven by minlength rules on the input */
.lf-str-row:has(input[type="password"][value=""])           .lf-str-fill { width: 0; }
.lf-str-row:has(input[type="password"]:invalid)             .lf-str-fill { width: 30%; }
.lf-str-row:has(input[type="password"]:valid)               .lf-str-fill { width: 60%; }
/* attribute selector — pattern-match longer values for full bar */
.lf-str-row:has(input[type="password"][minlength]:valid)
  > input[type="password"]:not(:placeholder-shown):required { /* selector keepalive */ }
.lf-str-row:has(input:focus:valid) .lf-str-fill { width: 100%; }
.lf-str-hint { font-size: 10.5px; color: #6b6987; line-height: 1.5; }
.lf-str-btn {
  margin-top: 4px; padding: 11px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 8px;
  font-size: 13px; font-weight: 600; cursor: pointer;
  transition: transform .12s;
}
.lf-str-btn:hover { transform: translateY(-1px); }
<form class="lf-str" aria-label="Sign up with strength meter">
  <h2 class="lf-str-title">Create account</h2>
  <label class="lf-str-row">
    <span>Email</span>
    <input type="email" name="email" autocomplete="email" placeholder="[email protected]" required />
  </label>
  <label class="lf-str-row">
    <span>Password</span>
    <input type="password" name="password" autocomplete="new-password" placeholder="At least 12 characters" minlength="6" required />
    <span class="lf-str-meter" aria-hidden="true">
      <span class="lf-str-fill"></span>
    </span>
    <span class="lf-str-hint">Use 12+ characters with a mix of letters, numbers, and symbols.</span>
  </label>
  <button type="submit" class="lf-str-btn">Create account</button>
</form>
21 / 24
Pin Pad
Pure CSS

Enter PIN

Numeric PIN login form. A 3×4 keypad styled like a hardware keypad with live filled-dot indicator — perfect for kiosks, secure dashboards, and short PIN auth flows.
.lf-pin {
  width: 100%; max-width: 240px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 16px;
  padding: 22px 20px 18px;
  display: grid; gap: 14px;
  text-align: center;
}
.lf-pin-title { margin: 0; font-size: 14px; font-weight: 700; color: #f0eeff; letter-spacing: 0.04em; }
.lf-pin-display {
  display: flex; gap: 12px; justify-content: center;
  padding: 8px 0;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.lf-pin-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: rgba(255,255,255,0.12);
  transition: background .2s, transform .2s;
}
.lf-pin-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
}
.lf-pin-key {
  aspect-ratio: 1 / 1;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  font-size: 16px; font-weight: 600;
  color: #f0eeff;
  cursor: pointer;
  transition: background .12s, transform .08s, border-color .15s;
}
.lf-pin-key:hover { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.18); }
.lf-pin-key:active { transform: scale(0.95); background: rgba(124,108,255,0.18); }
.lf-pin-key-fn { color: #9d9bbf; }
.lf-pin-key-go {
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border-color: transparent;
}
.lf-pin-key-go:hover { transform: translateY(-1px); }
<form class="lf-pin" aria-label="Numeric pin sign in">
  <h2 class="lf-pin-title">Enter PIN</h2>
  <div class="lf-pin-display" aria-live="polite">
    <span class="lf-pin-dot"></span>
    <span class="lf-pin-dot"></span>
    <span class="lf-pin-dot"></span>
    <span class="lf-pin-dot"></span>
  </div>
  <div class="lf-pin-grid" role="group" aria-label="Numeric keypad">
    <button type="button" class="lf-pin-key">1</button>
    <button type="button" class="lf-pin-key">2</button>
    <button type="button" class="lf-pin-key">3</button>
    <button type="button" class="lf-pin-key">4</button>
    <button type="button" class="lf-pin-key">5</button>
    <button type="button" class="lf-pin-key">6</button>
    <button type="button" class="lf-pin-key">7</button>
    <button type="button" class="lf-pin-key">8</button>
    <button type="button" class="lf-pin-key">9</button>
    <button type="button" class="lf-pin-key lf-pin-key-fn">⌫</button>
    <button type="button" class="lf-pin-key">0</button>
    <button type="submit" class="lf-pin-key lf-pin-key-go">→</button>
  </div>
</form>
22 / 24
Inline Validation
Pure CSS

Sign in

Inputs validate as you type

Login form with real-time inline validation. Each field shows a green checkmark when valid and a red icon when invalid, driven by `:valid` / `:invalid` and pseudo-elements — no JavaScript.
.lf-val {
  width: 100%; max-width: 320px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 14px;
  padding: 26px 22px;
  display: grid; gap: 12px;
}
.lf-val-title { margin: 0; font-size: 17px; font-weight: 700; color: #f0eeff; }
.lf-val-sub { margin: -6px 0 4px; font-size: 12px; color: #9d9bbf; }
.lf-val-row {
  display: grid; gap: 5px;
  font-size: 11px; color: #9d9bbf;
  position: relative;
}
.lf-val-row input {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 10px 38px 10px 12px;
  font-size: 13px;
  color: #f0eeff; outline: none;
  transition: border-color .15s, background .15s;
}
.lf-val-row input:focus { border-color: #7c6cff; }
.lf-val-row::after {
  content: ''; position: absolute;
  right: 12px; bottom: 12px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: transparent;
  transform: scale(0.5); opacity: 0;
  transition: transform .2s, opacity .2s, background .2s;
}
.lf-val-row:has(input:not(:placeholder-shown):invalid) input { border-color: rgba(255,108,138,0.6); }
.lf-val-row:has(input:not(:placeholder-shown):invalid)::after {
  opacity: 1; transform: scale(1);
  background: #ff6c8a
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10' fill='none' stroke='white' stroke-width='1.6' stroke-linecap='round'><path d='M2 2 L8 8 M8 2 L2 8'/></svg>") center/10px no-repeat;
}
.lf-val-row:has(input:not(:placeholder-shown):valid) input { border-color: rgba(46,184,138,0.55); }
.lf-val-row:has(input:not(:placeholder-shown):valid)::after {
  opacity: 1; transform: scale(1);
  background: #2eb88a
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10' fill='none' stroke='white' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M2 5 L4.2 7.2 L8 3'/></svg>") center/10px no-repeat;
}
.lf-val-btn {
  margin-top: 4px; padding: 11px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 8px;
  font-size: 13px; font-weight: 600; cursor: pointer;
  transition: transform .12s;
}
.lf-val-btn:hover { transform: translateY(-1px); }
<form class="lf-val" aria-label="Sign in with inline validation">
  <h2 class="lf-val-title">Sign in</h2>
  <p class="lf-val-sub">Inputs validate as you type</p>
  <label class="lf-val-row">
    <span>Email</span>
    <input type="email" name="email" autocomplete="email" placeholder="[email protected]" required />
  </label>
  <label class="lf-val-row">
    <span>Password</span>
    <input type="password" name="password" autocomplete="current-password" placeholder="At least 8 characters" minlength="8" required />
  </label>
  <button type="submit" class="lf-val-btn">Continue</button>
</form>
23 / 24
Constellation
Pure CSS

Welcome traveller

Sign in to continue your journey

Animated starfield login form. A subtle constellation drifts behind the card with staggered twinkling stars and periodic shooting-star streaks.
.lf-cons {
  position: relative; isolation: isolate;
  width: 100%; max-width: 320px;
  border-radius: 18px; overflow: hidden;
  background: radial-gradient(ellipse at top, #1a1838 0%, #07071a 70%);
}
.lf-cons-sky {
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
}
.lf-cons-star {
  position: absolute;
  width: 2px; height: 2px;
  background: white; border-radius: 50%;
  box-shadow: 0 0 4px rgba(255,255,255,0.8);
  animation: lfConsTwinkle 3s ease-in-out infinite;
}
.lf-cons-star.s1 { top: 12%; left: 18%; animation-delay: 0s; }
.lf-cons-star.s2 { top: 24%; left: 70%; animation-delay: 0.6s; }
.lf-cons-star.s3 { top: 38%; left: 32%; animation-delay: 1.2s; width: 1.5px; height: 1.5px; }
.lf-cons-star.s4 { top: 54%; left: 84%; animation-delay: 1.8s; }
.lf-cons-star.s5 { top: 68%; left: 14%; animation-delay: 0.3s; width: 1.5px; height: 1.5px; }
.lf-cons-star.s6 { top: 80%; left: 56%; animation-delay: 1s; }
@keyframes lfConsTwinkle {
  0%, 100% { opacity: 0.35; transform: scale(0.8); }
  50%      { opacity: 1; transform: scale(1.4); }
}
.lf-cons-shoot {
  position: absolute; top: 18%; left: -10%;
  width: 60px; height: 1.5px;
  background: linear-gradient(90deg, transparent, #fff, transparent);
  transform: rotate(-18deg);
  animation: lfConsShoot 6s ease-in infinite;
  opacity: 0;
}
@keyframes lfConsShoot {
  0%, 88%   { transform: translateX(0) rotate(-18deg); opacity: 0; }
  92%       { opacity: 1; }
  100%      { transform: translateX(380px) rotate(-18deg); opacity: 0; }
}
.lf-cons-card {
  position: relative; z-index: 1;
  margin: 22px;
  padding: 22px;
  border-radius: 14px;
  background: rgba(7,7,26,0.55);
  border: 1px solid rgba(255,255,255,0.12);
  backdrop-filter: blur(10px);
  display: grid; gap: 11px;
}
.lf-cons-title { margin: 0; font-size: 16px; font-weight: 700; color: #fff; }
.lf-cons-sub { margin: -6px 0 4px; font-size: 12px; color: rgba(255,255,255,0.6); }
.lf-cons-row input {
  width: 100%; box-sizing: border-box;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 8px;
  padding: 10px 12px; font-size: 13px;
  color: #fff; outline: none;
  transition: border-color .15s;
}
.lf-cons-row input::placeholder { color: rgba(255,255,255,0.4); }
.lf-cons-row input:focus { border-color: rgba(255,255,255,0.5); }
.lf-cons-btn {
  margin-top: 4px; padding: 10px;
  background: linear-gradient(135deg, #c4b5fd, #818cf8);
  color: #07071a; border: none; border-radius: 8px;
  font-size: 13px; font-weight: 700; cursor: pointer;
  transition: transform .12s;
}
.lf-cons-btn:hover { transform: translateY(-1px); }
<form class="lf-cons" aria-label="Constellation sign in">
  <div class="lf-cons-sky" aria-hidden="true">
    <span class="lf-cons-star s1"></span>
    <span class="lf-cons-star s2"></span>
    <span class="lf-cons-star s3"></span>
    <span class="lf-cons-star s4"></span>
    <span class="lf-cons-star s5"></span>
    <span class="lf-cons-star s6"></span>
    <span class="lf-cons-shoot"></span>
  </div>
  <article class="lf-cons-card">
    <h2 class="lf-cons-title">Welcome traveller</h2>
    <p class="lf-cons-sub">Sign in to continue your journey</p>
    <label class="lf-cons-row">
      <input type="email" name="email" autocomplete="email" placeholder="Email" required />
    </label>
    <label class="lf-cons-row">
      <input type="password" name="password" autocomplete="current-password" placeholder="Password" required />
    </label>
    <button type="submit" class="lf-cons-btn">Continue</button>
  </article>
</form>
24 / 24
Biometric Prompt
Pure CSS

Use your passkey

Touch the sensor or use Face ID


or sign in with password
Biometric / passkey login form. A fingerprint button takes centre stage with an animated scan line; email + password stay available below as a quiet fallback inside `<details>`.
.lf-bio {
  width: 100%; max-width: 280px;
  background: #15151d;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 16px;
  padding: 28px 22px 22px;
  display: grid; gap: 8px; justify-items: center;
  text-align: center;
}
.lf-bio-print {
  position: relative;
  width: 86px; height: 86px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, #2a2a36 0%, #0a0a14 70%);
  border: 1px solid rgba(124,108,255,0.4);
  color: #c8c0ff;
  display: grid; place-items: center;
  cursor: pointer;
  overflow: hidden;
  box-shadow: 0 0 0 4px rgba(124,108,255,0.05), 0 8px 24px -8px rgba(124,108,255,0.45);
  transition: transform .15s, box-shadow .25s;
}
.lf-bio-print:hover {
  transform: translateY(-1px);
  box-shadow: 0 0 0 6px rgba(124,108,255,0.1), 0 12px 32px -8px rgba(124,108,255,0.6);
}
.lf-bio-scan {
  position: absolute; left: 0; right: 0; top: 0;
  height: 12px;
  background: linear-gradient(180deg, transparent, rgba(124,108,255,0.65), transparent);
  animation: lfBioScan 2.4s ease-in-out infinite;
}
@keyframes lfBioScan {
  0%, 100% { transform: translateY(0); opacity: 0.9; }
  50%      { transform: translateY(74px); opacity: 1; }
}
.lf-bio-title { margin: 8px 0 0; font-size: 14px; font-weight: 700; color: #f0eeff; }
.lf-bio-sub { margin: 0; font-size: 12px; color: #9d9bbf; }
.lf-bio-divider {
  width: 100%; margin: 8px 0 4px;
  border: 0; border-top: 1px solid rgba(255,255,255,0.07);
}
.lf-bio-fallback { width: 100%; text-align: left; }
.lf-bio-fallback summary {
  font-size: 11px; color: #a78bfa;
  cursor: pointer; list-style: none;
  padding: 4px 0; text-align: center;
  user-select: none;
}
.lf-bio-fallback summary::-webkit-details-marker { display: none; }
.lf-bio-fallback summary:hover { color: #c8c0ff; }
.lf-bio-fallback[open] { display: grid; gap: 8px; }
.lf-bio-fallback[open] summary { margin-bottom: 4px; }
.lf-bio-row input {
  width: 100%; box-sizing: border-box;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  padding: 9px 12px; font-size: 13px;
  color: #f0eeff; outline: none;
  transition: border-color .15s;
}
.lf-bio-row input:focus { border-color: #7c6cff; }
.lf-bio-submit {
  width: 100%; padding: 9px;
  background: linear-gradient(135deg, #7c6cff, #ff6c8a);
  color: white; border: none; border-radius: 8px;
  font-size: 12px; font-weight: 600; cursor: pointer;
}
<form class="lf-bio" aria-label="Biometric or password sign in">
  <button type="button" class="lf-bio-print" aria-label="Sign in with passkey">
    <svg viewBox="0 0 64 64" width="40" height="40" aria-hidden="true">
      <g fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round">
        <path d="M16 38c0-10 7-18 16-18s16 8 16 18"/>
        <path d="M22 42c0-7 4.5-12 10-12s10 5 10 12"/>
        <path d="M28 46c0-4 1.5-7 4-7s4 3 4 7"/>
        <path d="M14 28c4-6 10-10 18-10s14 4 18 10"/>
      </g>
    </svg>
    <span class="lf-bio-scan" aria-hidden="true"></span>
  </button>
  <h2 class="lf-bio-title">Use your passkey</h2>
  <p class="lf-bio-sub">Touch the sensor or use Face ID</p>
  <hr class="lf-bio-divider" />
  <details class="lf-bio-fallback">
    <summary>or sign in with password</summary>
    <label class="lf-bio-row">
      <input type="email" name="email" autocomplete="email" placeholder="Email" required />
    </label>
    <label class="lf-bio-row">
      <input type="password" name="password" autocomplete="current-password" placeholder="Password" required />
    </label>
    <button type="submit" class="lf-bio-submit">Sign in</button>
  </details>
</form>

Related collections