24 CSS Login Form Designs with Live Demos
OTP Verify
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.
OTP Verify the 19th of 24 designs in the 24 CSS Login Form Designs with Live Demos collection. The design pairs CSS styling with a small amount of JavaScript for interactivity. Copy the HTML, CSS and JavaScript panels below into your project — the JS is self-contained, has zero dependencies, and is safe to drop into any framework (React, Vue, Svelte, plain HTML). The design honours prefers-reduced-motion and uses real semantic markup, so it ships accessibility-ready out of the box.
Live preview
The code
<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 & sign in</button> <p class="lf-otp-foot">Didn't get it? <a href="#">Resend code</a></p> </form>
.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: #b8b6d4;
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 0.15s,
background 0.15s,
transform 0.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: #b8b6d4;
}
.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();
});
});
*/ // OTP auto-advance + backspace navigation + paste
document.querySelectorAll('.lf-otp-row').forEach(function (row) {
var inputs = Array.prototype.slice.call(row.querySelectorAll('[data-lf-otp]'));
inputs.forEach(function (input, i) {
input.addEventListener('input', function () {
input.value = (input.value || '').replace(/D/g, '').slice(0, 1);
if (input.value && inputs[i + 1]) inputs[i + 1].focus();
});
input.addEventListener('keydown', function (e) {
if (e.key === 'Backspace' && !input.value && inputs[i - 1]) {
inputs[i - 1].focus();
}
});
input.addEventListener('paste', function (e) {
var data = (e.clipboardData || window.clipboardData).getData('text');
var digits = (data || '').replace(/D/g, '').slice(0, inputs.length);
if (!digits) return;
e.preventDefault();
for (var j = 0; j < digits.length; j++) {
if (inputs[i + j]) inputs[i + j].value = digits[j];
}
var next = Math.min(i + digits.length, inputs.length - 1);
inputs[next].focus();
});
});
}); More from 24 CSS Login Form Designs with Live Demos
Animated MascotCompact ModalGlass FrostedStep-by-StepAnimated Gradient BorderVault LockBrutalist StampStrength MeterPin PadInline ValidationConstellationBiometric Prompt
View the full collection →