SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/login-forms

8 CSS Login Forms

5 Pure CSS3 with JSPublished 2026-10-04Free · no sign-up

Eight login and sign-up screens written in plain HTML and CSS, with a little JavaScript where a demo shows a state change. They cover a classic card, a split layout, provider buttons, a frosted-glass panel, a passwordless magic link, an error summary, a minimal admin login and a sign-up form with live password rules.

01. Simple Sign-In Card

AuthCard

A clean sign-in card with email, password, a remember-me checkbox and a forgot-password link. Every field has a visible label and the right autocomplete token, so password managers and browsers fill it correctly, and the primary button is full width.

View code
<form class="lg" onsubmit="event.preventDefault()">
  <h1>Sign in</h1>
  <label for="lg-e">Email</label>
  <input id="lg-e" type="email" autocomplete="email" required>
  <div class="lab"><label for="lg-p">Password</label><a href="#">Forgot password?</a></div>
  <input id="lg-p" type="password" autocomplete="current-password" required>
  <label class="chk"><input type="checkbox"> Keep me signed in</label>
  <button>Sign in</button>
  <p class="foot">New here? <a href="#">Create an account</a></p>
</form>
.lg { box-sizing: border-box; max-width: 100%; display: grid; gap: 8px; width: min(360px, 90vw); padding: 28px; border-radius: 18px; background: #fff; box-shadow: 0 18px 40px -18px rgba(16,24,40,.35); font: 500 14px Inter, system-ui, sans-serif; color: #344054; }
.lg h1 { margin: 0 0 10px; color: #101828; font-size: 22px; }
.lg input:not([type=checkbox]) { padding: 11px 12px; margin-bottom: 8px; border: 1.5px solid #d0d5dd; border-radius: 10px; font-size: 15px; outline: none; }
.lg input:focus { border-color: #2563eb; box-shadow: 0 0 0 3px rgba(37,99,235,.15); }
.lab { display: flex; justify-content: space-between; }
.lg a { color: #1d4ed8; font-weight: 600; text-decoration: none; }
.lg a:hover { text-decoration: underline; }
.chk { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.lg button { padding: 12px; border: 0; border-radius: 10px; background: #2563eb; color: #fff; font: 700 15px Inter, sans-serif; cursor: pointer; }
.lg button:hover { background: #1d4ed8; }
.foot { margin: 8px 0 0; text-align: center; }

02. Split Screen Login

AuthLayout

A two-panel login: a branded colour panel with a short message on the left and the form on the right. Below 640 pixels the brand panel shrinks to a header strip, so the form stays first and fully usable on phones.

View code
<div class="spl">
  <aside><p class="brand">Harbor</p><p class="msg">Run your shop from one calm dashboard.</p></aside>
  <form onsubmit="event.preventDefault()">
    <h1>Welcome back</h1>
    <label for="sp-e">Work email</label><input id="sp-e" type="email" autocomplete="email">
    <label for="sp-p">Password</label><input id="sp-p" type="password" autocomplete="current-password">
    <button>Continue</button>
  </form>
</div>
.spl { display: grid; grid-template-columns: 1fr 1.2fr; width: min(640px, 94vw); overflow: hidden; border-radius: 18px; background: #fff; box-shadow: 0 18px 40px -18px rgba(16,24,40,.35); font-family: Inter, system-ui, sans-serif; }
.spl aside { display: flex; flex-direction: column; justify-content: space-between; padding: 26px; background: linear-gradient(160deg, #0f766e, #134e4a); color: #fff; }
.brand { margin: 0; font-weight: 800; font-size: 18px; }
.msg { margin: 0; font-size: 20px; font-weight: 700; line-height: 1.3; }
.spl form { display: grid; gap: 6px; padding: 28px; color: #344054; font-size: 14px; font-weight: 600; }
.spl h1 { margin: 0 0 8px; color: #101828; font-size: 21px; }
.spl input { margin-bottom: 8px; padding: 11px 12px; border: 1.5px solid #d0d5dd; border-radius: 10px; font: 15px Inter, sans-serif; outline: none; }
.spl input:focus { border-color: #0f766e; box-shadow: 0 0 0 3px rgba(15,118,110,.18); }
.spl button { margin-top: 6px; padding: 12px; border: 0; border-radius: 10px; background: #0f766e; color: #fff; font: 700 15px Inter, sans-serif; cursor: pointer; }
@media (max-width: 640px) { .spl { grid-template-columns: 1fr; } .spl aside { flex-direction: row; align-items: center; gap: 12px; padding: 16px 20px; } .msg { font-size: 14px; } }

03. Login with Social Buttons

AuthOAuth

A dark sign-in panel with provider buttons above an or divider and an email form below. The provider buttons use neutral icons drawn in CSS, so you can drop in each provider's official logo artwork when you add their real sign-in flow.

View code
<form class="soc" onsubmit="event.preventDefault()">
  <h1>Log in to Studio</h1>
  <button type="button" class="prov"><span class="ic g" aria-hidden="true"></span>Continue with Google</button>
  <button type="button" class="prov"><span class="ic a" aria-hidden="true"></span>Continue with Apple</button>
  <p class="or"><span>or</span></p>
  <label for="so-e">Email</label>
  <input id="so-e" type="email" autocomplete="email" placeholder="you@studio.com">
  <button class="go">Send me a login link</button>
</form>
.soc { box-sizing: border-box; max-width: 100%; display: grid; gap: 10px; width: min(360px, 90vw); padding: 28px; border: 1px solid #262d3e; border-radius: 18px; background: #12161f; color: #c9d1e2; font: 500 14px Inter, system-ui, sans-serif; }
.soc h1 { margin: 0 0 6px; color: #fff; font-size: 21px; }
.prov { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 11px; border: 1px solid #343c51; border-radius: 10px; background: #1a1f2c; color: #e7ebf5; font: 600 14px Inter, sans-serif; cursor: pointer; }
.prov:hover { background: #212838; }
.ic { width: 16px; height: 16px; border-radius: 50%; }
.ic.g { background: conic-gradient(#ea4335 0 25%, #fbbc05 0 50%, #34a853 0 75%, #4285f4 0); }
.ic.a { background: #e7ebf5; border-radius: 40% 40% 50% 50%; }
.or { position: relative; margin: 6px 0; text-align: center; color: #8b95a9; }
.or::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; border-top: 1px solid #262d3e; }
.or span { position: relative; padding: 0 10px; background: #12161f; }
.soc input { padding: 11px 12px; border: 1px solid #343c51; border-radius: 10px; background: #0d1018; color: #fff; font-size: 15px; outline: none; }
.soc input:focus { border-color: #a78bfa; }
.go { padding: 12px; border: 0; border-radius: 10px; background: #a78bfa; color: #120c26; font: 700 15px Inter, sans-serif; cursor: pointer; }
.soc button:focus-visible { outline: 2px solid #c4b5fd; outline-offset: 2px; }

04. Glass Login over Gradient

GlassAuth

A frosted-glass sign-in panel floating over colourful blurred shapes. The panel uses backdrop-filter with a translucent fill, and the text and fields sit on a dark enough tint that they keep a readable contrast even where the shapes behind are bright.

View code
<div class="gl-bg">
  <span class="o1"></span><span class="o2"></span>
  <form class="gl" onsubmit="event.preventDefault()">
    <h1>Member login</h1>
    <label for="gl-u">Username</label><input id="gl-u" autocomplete="username">
    <label for="gl-p">Password</label><input id="gl-p" type="password" autocomplete="current-password">
    <button>Log in</button>
  </form>
</div>
.gl-bg { position: relative; display: grid; place-items: center; width: min(460px, 94vw); height: 380px; overflow: hidden; border-radius: 22px; background: #0b0e1a; }
.gl-bg span { position: absolute; border-radius: 50%; filter: blur(4px); }
.o1 { width: 220px; height: 220px; left: -40px; top: -30px; background: #6366f1; }
.o2 { width: 200px; height: 200px; right: -30px; bottom: -40px; background: #ec4899; }
.gl { position: relative; display: grid; gap: 6px; width: 280px; padding: 26px; border: 1px solid rgba(255,255,255,.22); border-radius: 18px; background: rgba(15,18,34,.55); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); color: #e6e9f5; font: 600 13px Inter, system-ui, sans-serif; }
.gl h1 { margin: 0 0 8px; color: #fff; font-size: 20px; }
.gl input { margin-bottom: 8px; padding: 10px 12px; border: 1px solid rgba(255,255,255,.25); border-radius: 10px; background: rgba(0,0,0,.25); color: #fff; font: 15px Inter, sans-serif; outline: none; }
.gl input:focus { border-color: #fff; }
.gl button { margin-top: 6px; padding: 11px; border: 0; border-radius: 10px; background: #fff; color: #111; font: 700 15px Inter, sans-serif; cursor: pointer; }
.gl button:focus-visible { outline: 2px solid #f9a8d4; outline-offset: 2px; }

05. Passwordless Magic Link

AuthState

A one-field login that emails a sign-in link. Submitting swaps the form for a confirmation that names the address, and focus moves to the confirmation heading so keyboard and screen reader users land on the new message.

View code
<div class="mg">
  <form id="mg-f" onsubmit="event.preventDefault()">
    <h1>Sign in without a password</h1>
    <p>We will email you a link that signs you in.</p>
    <label for="mg-e">Email</label>
    <input id="mg-e" type="email" autocomplete="email" required value="dana@example.com">
    <button>Email me a link</button>
  </form>
  <div id="mg-done" hidden>
    <h2 tabindex="-1">Check your inbox</h2>
    <p>We sent a link to <b id="mg-addr"></b>. It works for 15 minutes.</p>
  </div>
</div>
.mg { box-sizing: border-box; max-width: 100%; width: min(360px, 90vw); padding: 28px; border-radius: 18px; background: #fff; box-shadow: 0 18px 40px -18px rgba(16,24,40,.35); font-family: Inter, system-ui, sans-serif; color: #475467; }
.mg form { display: grid; gap: 8px; }
.mg h1, .mg h2 { margin: 0; color: #101828; font-size: 20px; }
.mg p { margin: 0 0 6px; font-size: 14px; line-height: 1.5; }
.mg label { color: #344054; font-size: 14px; font-weight: 600; }
.mg input { padding: 11px 12px; border: 1.5px solid #d0d5dd; border-radius: 10px; font: 15px Inter, sans-serif; outline: none; }
.mg input:focus { border-color: #7c3aed; box-shadow: 0 0 0 3px rgba(124,58,237,.15); }
.mg button { margin-top: 4px; padding: 12px; border: 0; border-radius: 10px; background: #7c3aed; color: #fff; font: 700 15px Inter, sans-serif; cursor: pointer; }
#mg-done h2 { margin-bottom: 8px; outline: none; }
document.getElementById('mg-f').addEventListener('submit', e => {
  document.getElementById('mg-addr').textContent = document.getElementById('mg-e').value;
  e.target.hidden = true;
  const done = document.getElementById('mg-done');
  done.hidden = false;
  done.querySelector('h2').focus();
});

06. Login with Error Summary

ValidationAccessible

When sign-in fails, an error summary appears at the top of the form with role="alert" and a link to the field to fix. The wrong field is marked with aria-invalid and its own message, following the error-summary pattern used by public-service sites.

View code
<form class="er" novalidate>
  <div class="sum" role="alert" hidden>
    <h2>There is a problem</h2>
    <a href="#er-p">Enter your password</a>
  </div>
  <h1>Sign in</h1>
  <label for="er-e">Email</label>
  <input id="er-e" type="email" autocomplete="email" value="lee@example.com">
  <label for="er-p">Password</label>
  <p class="msg" id="er-pm" hidden>Enter your password</p>
  <input id="er-p" type="password" autocomplete="current-password" aria-describedby="er-pm">
  <button>Sign in</button>
</form>
.er { box-sizing: border-box; max-width: 100%; display: grid; gap: 6px; width: min(360px, 90vw); padding: 26px; border-radius: 16px; background: #fff; box-shadow: 0 18px 40px -18px rgba(16,24,40,.35); font: 600 14px Inter, system-ui, sans-serif; color: #344054; }
.er h1 { margin: 0 0 8px; color: #101828; font-size: 21px; }
.sum { margin-bottom: 10px; padding: 14px; border: 3px solid #d92d20; border-radius: 10px; }
.sum h2 { margin: 0 0 6px; color: #101828; font-size: 16px; }
.sum a { color: #b42318; }
.er input { margin-bottom: 8px; padding: 11px 12px; border: 1.5px solid #d0d5dd; border-radius: 10px; font: 15px Inter, sans-serif; outline: none; }
.er input[aria-invalid="true"] { border: 2px solid #d92d20; }
.msg { margin: 0; color: #b42318; }
.er button { margin-top: 6px; padding: 12px; border: 0; border-radius: 10px; background: #101828; color: #fff; font: 700 15px Inter, sans-serif; cursor: pointer; }
const f = document.querySelector('.er');
f.addEventListener('submit', e => {
  e.preventDefault();
  const p = document.getElementById('er-p'), bad = !p.value;
  p.setAttribute('aria-invalid', String(bad));
  document.getElementById('er-pm').hidden = !bad;
  f.querySelector('.sum').hidden = !bad;
  if (bad) f.querySelector('.sum a').focus();
});

07. Minimal Underline Login

MinimalAuth

A pared-back login for portfolio sites and admin panels: underline fields, generous spacing and one quiet button. Because the borders are subtle, focus is shown with a bright underline and the labels stay visible above each field at all times.

View code
<form class="mn" onsubmit="event.preventDefault()">
  <p class="eyebrow">Admin</p>
  <label for="mn-u">Username</label>
  <input id="mn-u" autocomplete="username">
  <label for="mn-p">Password</label>
  <input id="mn-p" type="password" autocomplete="current-password">
  <button>Enter &rarr;</button>
</form>
.mn { display: grid; gap: 6px; width: min(300px, 86vw); color: #8b95a9; font: 500 12px Inter, system-ui, sans-serif; text-transform: uppercase; letter-spacing: .12em; }
.eyebrow { margin: 0 0 18px; color: #fff; font-size: 22px; font-weight: 800; letter-spacing: 0; text-transform: none; }
.mn input { margin-bottom: 18px; padding: 8px 0; border: 0; border-bottom: 1px solid #3a4256; background: none; color: #fff; font: 16px Inter, sans-serif; letter-spacing: 0; outline: none; }
.mn input:focus { border-bottom: 2px solid #fbbf24; padding-bottom: 7px; }
.mn button { justify-self: start; padding: 10px 0; border: 0; background: none; color: #fbbf24; font: 700 15px Inter, sans-serif; letter-spacing: .04em; cursor: pointer; }
.mn button:focus-visible { outline: 2px solid #fbbf24; outline-offset: 4px; }

08. Sign-Up with Password Rules

AuthValidation

A create-account form that shows password rules as a checklist and ticks each one live as you type. The checklist is linked to the field with aria-describedby, and each rule changes both its icon and its text colour, not colour alone.

View code
<form class="su" onsubmit="event.preventDefault()">
  <h1>Create your account</h1>
  <label for="su-n">Name</label><input id="su-n" autocomplete="name">
  <label for="su-e">Email</label><input id="su-e" type="email" autocomplete="email">
  <label for="su-p">Password</label>
  <input id="su-p" type="password" autocomplete="new-password" aria-describedby="su-rules" value="shop2026">
  <ul id="su-rules">
    <li data-r="len">At least 10 characters</li>
    <li data-r="num">Contains a number</li>
    <li data-r="case">Upper and lower case letters</li>
  </ul>
  <button>Create account</button>
</form>
.su { box-sizing: border-box; max-width: 100%; display: grid; gap: 6px; width: min(360px, 90vw); padding: 26px; border-radius: 18px; background: #fff; box-shadow: 0 18px 40px -18px rgba(16,24,40,.35); font: 600 14px Inter, system-ui, sans-serif; color: #344054; }
.su h1 { margin: 0 0 8px; color: #101828; font-size: 21px; }
.su input { margin-bottom: 8px; padding: 10px 12px; border: 1.5px solid #d0d5dd; border-radius: 10px; font: 15px Inter, sans-serif; outline: none; }
.su input:focus { border-color: #2563eb; box-shadow: 0 0 0 3px rgba(37,99,235,.15); }
.su ul { display: grid; gap: 4px; margin: -2px 0 10px; padding: 0; list-style: none; font-weight: 500; font-size: 13px; }
.su li { color: #5d6679; }
.su li::before { content: "\25CB  "; }
.su li.ok { color: #067647; }
.su li.ok::before { content: "\2713  "; }
.su button { padding: 12px; border: 0; border-radius: 10px; background: #2563eb; color: #fff; font: 700 15px Inter, sans-serif; cursor: pointer; }
const pw = document.getElementById('su-p');
const tests = { len: v => v.length >= 10, num: v => /\d/.test(v), case: v => /[a-z]/.test(v) && /[A-Z]/.test(v) };
function check() {
  document.querySelectorAll('#su-rules li').forEach(li => li.classList.toggle('ok', tests[li.dataset.r](pw.value)));
}
pw.addEventListener('input', check);
check();

About these CSS Login Forms

Autocomplete makes login easier

Password managers rely on the autocomplete attribute. Use email or username for the account field, current-password on sign-in and new-password on sign-up so the manager offers to generate a strong password. Never block pasting into password fields.

Errors that help

When sign-in fails, tell people what to do next without revealing whether the email exists. The error summary demo shows a box at the top with role="alert" and a link to the field, and marks the field itself with aria-invalid and an inline message.

Passwordless options

Magic links and one-time codes remove passwords entirely. After the request, replace the form with a clear confirmation and move focus to its heading, so keyboard and screen reader users notice the change.

Provider buttons

Sign in with Google or Apple buttons must follow each provider's own brand rules and use their official artwork. The social demo uses neutral placeholders so you can drop in the official assets when you connect the real flows.

Frequently asked questions

Are these forms secure?

They are front-end templates. Security depends on your server: use HTTPS, hash passwords and rate-limit attempts.

Can I use them with any backend?

Yes. They are standard HTML forms; set the action and method for your server or connect them with fetch.

Do they work on phones?

Yes. Fields are full width, and the split layout collapses to one column below 640 pixels.