A progressive disclosure login form built with pure HTML and CSS that reveals input fields gradually based on user interaction. It enhances focused input flow and reduced cognitive load in authentication interfaces.
Usage
Use this component when interfaces require step by step field visibility, such as email first login, multi stage authentication, onboarding flows, or minimal login screens that guide users progressively.
Implementation
The layout is implemented using CSS state selectors and conditional visibility techniques, allowing fields to appear in sequence without JavaScript. Responsive styling ensures smooth alignment across screen sizes.
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@300;400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="login.css">
</head>
<body>
<!-- Invisible anchor targets for CSS :target state -->
<span id="step2" class="anchor-target"></span>
<span id="step3" class="anchor-target"></span>
<div class="card">
<!-- Step progress marks -->
<div class="step-marks">
<span class="mark-1"></span>
<span class="mark-2"></span>
<span class="mark-3"></span>
</div>
<!-- Dynamic heading -->
<div class="heading-group">
<p class="eyebrow eyebrow-1">Step 1 of 3 — Identify</p>
<p class="eyebrow eyebrow-2">Step 2 of 3 — Authenticate</p>
<p class="eyebrow eyebrow-3">Step 3 of 3 — Confirm</p>
<h1 class="h1-1">Sign <em>in</em><br>to continue.</h1>
<h1 class="h1-2">Enter your<br><em>password.</em></h1>
<h1 class="h1-3">Almost<br><em>there.</em></h1>
</div>
<!-- STEP 1: Email -->
<div class="step-1">
<div class="field">
<label for="email">Email address</label>
<input type="email" id="email" placeholder="[email protected]" autocomplete="email">
</div>
<a href="#step2" class="btn">Continue</a>
<div class="divider"><span>or</span></div>
<a href="#" class="btn-ghost">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/>
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/>
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l3.66-2.84z" fill="#FBBC05"/>
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/>
</svg>
Continue with Google
</a>
<div class="footer-note">
No account? <a href="#">Create one</a> · <a href="#">Need help?</a>
</div>
</div>
<!-- STEP 2: Password -->
<div class="step-2">
<div class="user-display">
<div class="avatar">✉</div>
<span class="user-email-shown">[email protected]</span>
</div>
<div class="field">
<label for="password">Password</label>
<input type="password" id="password" placeholder="············" autocomplete="current-password">
<p class="field-hint">Min. 8 characters · case sensitive</p>
</div>
<div class="checkbox-row">
<input type="checkbox" id="remember" name="remember">
<label for="remember">Keep me signed in for 30 days</label>
</div>
<a href="#step3" class="btn">Sign in</a>
<a href="" class="back-link">Use a different email</a>
<div class="footer-note">
<a href="#">Forgot password?</a> · <a href="#">Sign in with SSO</a>
</div>
</div>
<!-- STEP 3: 2FA / Confirm -->
<div class="step-3">
<div class="success-icon">⩫</div>
<div class="field">
<label for="code">Verification code</label>
<input type="text" id="code" placeholder="_ _ _ _ _ _" maxlength="6" autocomplete="one-time-code">
<p class="field-hint">Sent to your email · expires in 10 min</p>
</div>
<a href="#" class="btn">Verify & Enter</a>
<a href="#step2" class="back-link">Back to password</a>
<div class="footer-note">
Didn't receive a code? <a href="#">Resend</a> · <a href="#">Try another method</a>
</div>
</div>
</div>
</body>
</html>CSS
:root {
--ink: #0f0e0d;
--paper: #f5f2ed;
--warm: #e8e2d9;
--accent: #c94f2a;
--accent-dim: #e8c4b8;
--muted: #8a857d;
--border: #d4cec6;
--field-bg: #faf8f5;
}
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'DM Mono', monospace;
background: var(--paper);
min-height: 100vh;
display: grid;
place-items: center;
padding: 2rem;
position: relative;
overflow: hidden;
}
/* Subtle grain texture */
body::before {
content: '';
position: fixed;
inset: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.04'/%3E%3C/svg%3E");
pointer-events: none;
z-index: 0;
}
/* Decorative corner marks */
body::after {
content: '';
position: fixed;
bottom: 3rem;
right: 3rem;
width: 80px;
height: 80px;
border-right: 1.5px solid var(--border);
border-bottom: 1.5px solid var(--border);
pointer-events: none;
z-index: 0;
}
.card {
position: relative;
z-index: 1;
width: 100%;
max-width: 420px;
background: #fff;
border: 1px solid var(--border);
padding: 3rem 3rem 2.5rem;
box-shadow:
4px 4px 0px var(--warm),
8px 8px 0px var(--border);
}
/* Top decorative rule */
.card::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 3px;
background: linear-gradient(90deg, var(--accent), var(--accent-dim), transparent);
}
/* Step indicator marks */
.step-marks {
display: flex;
gap: 6px;
margin-bottom: 2.5rem;
align-items: center;
}
.step-marks span {
display: block;
height: 2px;
background: var(--border);
transition: background 0.4s ease, width 0.4s ease;
}
.step-marks span:nth-child(1) { width: 40px; }
.step-marks span:nth-child(2) { width: 20px; }
.step-marks span:nth-child(3) { width: 20px; }
.heading-group {
margin-bottom: 2.5rem;
}
.eyebrow {
font-size: 0.65rem;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 0.5rem;
}
h1 {
font-family: 'DM Serif Display', serif;
font-size: 2.2rem;
line-height: 1.1;
color: var(--ink);
font-style: italic;
}
h1 em {
font-style: normal;
color: var(--accent);
}
/* ── Progressive Disclosure: CSS :target + :has() ── */
/* Default state: Step 1 visible */
.step-1 { display: block; }
.step-2 { display: none; }
.step-3 { display: none; }
/* When #step2 is targeted */
:root:has(#step2:target) .step-1 { display: none; }
:root:has(#step2:target) .step-2 { display: block; }
:root:has(#step2:target) .step-3 { display: none; }
:root:has(#step2:target) .mark-1 { background: var(--accent) !important; }
/* When #step3 is targeted */
:root:has(#step3:target) .step-1 { display: none; }
:root:has(#step3:target) .step-2 { display: none; }
:root:has(#step3:target) .step-3 { display: block; }
:root:has(#step3:target) .mark-1 { background: var(--accent) !important; }
:root:has(#step3:target) .mark-2 { background: var(--accent) !important; }
/* Eyebrow text changes per step */
.eyebrow-2, .eyebrow-3 { display: none; }
:root:has(#step2:target) .eyebrow-1 { display: none; }
:root:has(#step2:target) .eyebrow-2 { display: block; }
:root:has(#step2:target) .eyebrow-3 { display: none; }
:root:has(#step3:target) .eyebrow-1 { display: none; }
:root:has(#step3:target) .eyebrow-2 { display: none; }
:root:has(#step3:target) .eyebrow-3 { display: block; }
/* H1 changes per step */
.h1-2, .h1-3 { display: none; }
:root:has(#step2:target) .h1-1 { display: none; }
:root:has(#step2:target) .h1-2 { display: block; }
:root:has(#step2:target) .h1-3 { display: none; }
:root:has(#step3:target) .h1-1 { display: none; }
:root:has(#step3:target) .h1-2 { display: none; }
:root:has(#step3:target) .h1-3 { display: block; }
/* Anchor targets (invisible) */
.anchor-target {
position: absolute;
visibility: hidden;
pointer-events: none;
}
/* ── Form Fields ── */
.field {
margin-bottom: 1.5rem;
}
label {
display: block;
font-size: 0.65rem;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 0.5rem;
}
input[type="email"],
input[type="password"],
input[type="text"] {
width: 100%;
padding: 0.75rem 1rem;
font-family: 'DM Mono', monospace;
font-size: 0.9rem;
background: var(--field-bg);
border: 1px solid var(--border);
color: var(--ink);
outline: none;
transition: border-color 0.2s, box-shadow 0.2s;
-webkit-appearance: none;
appearance: none;
}
input[type="email"]:focus,
input[type="password"]:focus,
input[type="text"]:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-dim);
}
input::placeholder {
color: var(--border);
font-size: 0.85rem;
}
.field-hint {
font-size: 0.65rem;
color: var(--muted);
margin-top: 0.4rem;
letter-spacing: 0.05em;
}
/* Checkbox row */
.checkbox-row {
display: flex;
align-items: center;
gap: 0.6rem;
margin-bottom: 1.5rem;
}
input[type="checkbox"] {
width: 16px;
height: 16px;
accent-color: var(--accent);
cursor: pointer;
}
.checkbox-row label {
font-size: 0.72rem;
letter-spacing: 0.05em;
text-transform: none;
color: var(--muted);
margin: 0;
cursor: pointer;
}
/* ── Buttons ── */
.btn {
display: block;
width: 100%;
padding: 0.85rem 1rem;
background: var(--ink);
color: var(--paper);
font-family: 'DM Mono', monospace;
font-size: 0.75rem;
letter-spacing: 0.14em;
text-transform: uppercase;
text-decoration: none;
text-align: center;
border: none;
cursor: pointer;
transition: background 0.2s, transform 0.1s;
position: relative;
overflow: hidden;
}
.btn::after {
content: '→';
position: absolute;
right: 1.2rem;
top: 50%;
transform: translateY(-50%);
transition: transform 0.2s;
}
.btn:hover {
background: var(--accent);
}
.btn:hover::after {
transform: translateY(-50%) translateX(4px);
}
.btn:active {
transform: translateY(1px);
}
.back-link {
display: inline-block;
font-size: 0.65rem;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
text-decoration: none;
margin-top: 1.2rem;
padding-bottom: 1px;
border-bottom: 1px solid transparent;
transition: color 0.2s, border-color 0.2s;
}
.back-link:hover {
color: var(--ink);
border-color: var(--ink);
}
.back-link::before {
content: '← ';
}
/* ── Divider ── */
.divider {
display: flex;
align-items: center;
gap: 1rem;
margin: 1.5rem 0;
}
.divider::before,
.divider::after {
content: '';
flex: 1;
height: 1px;
background: var(--border);
}
.divider span {
font-size: 0.65rem;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
}
/* Ghost / Social button */
.btn-ghost {
display: flex;
align-items: center;
justify-content: center;
gap: 0.6rem;
width: 100%;
padding: 0.75rem 1rem;
background: transparent;
border: 1px solid var(--border);
font-family: 'DM Mono', monospace;
font-size: 0.72rem;
letter-spacing: 0.08em;
color: var(--ink);
text-decoration: none;
cursor: pointer;
transition: border-color 0.2s, background 0.2s;
}
.btn-ghost:hover {
border-color: var(--ink);
background: var(--field-bg);
}
.btn-ghost::after { content: none; }
/* ── Footer Note ── */
.footer-note {
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid var(--border);
font-size: 0.65rem;
color: var(--muted);
letter-spacing: 0.05em;
line-height: 1.6;
}
.footer-note a {
color: var(--ink);
text-decoration: none;
border-bottom: 1px solid var(--border);
transition: border-color 0.2s;
}
.footer-note a:hover {
border-color: var(--accent);
color: var(--accent);
}
/* ── Step 3 Elements ── */
.success-icon {
width: 48px;
height: 48px;
border: 2px solid var(--accent);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1.5rem;
font-size: 1.3rem;
color: var(--accent);
flex-shrink: 0;
}
.user-display {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
background: var(--field-bg);
border: 1px solid var(--border);
margin-bottom: 1.5rem;
}
.user-display .avatar {
width: 36px;
height: 36px;
background: var(--warm);
border: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
flex-shrink: 0;
}
.user-email-shown {
font-size: 0.75rem;
color: var(--muted);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ── Animations ── */
.step-1, .step-2, .step-3 {
animation: stepIn 0.35s ease forwards;
}
@keyframes stepIn {
from {
opacity: 0;
transform: translateY(8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* ── Responsive ── */
@media (max-width: 480px) {
.card {
padding: 2rem 1.75rem;
box-shadow: 3px 3px 0 var(--warm), 6px 6px 0 var(--border);
}
h1 { font-size: 1.8rem; }
}Notes
- Built with pure HTML and CSS
- No JavaScript required
- Uses progressive field reveal technique
- Enhances focused user input flow
- Fully responsive across breakpoints
- Suitable for modern authentication UX
- Easy to customize reveal transitions and spacing
Preview styles shown. Production customization recommended.
Browse More UI Components
Explore hundreds of reusable HTML & CSS UI components built for modern web projects.
Discover buttons, cards, loaders, animations, layouts, and more all with live previews and clean, copy-paste code.
