Open demo

CSS code

HTML
<div class="tb">
  <div class="tb-card">
    <div class="tb-tabs" role="tablist" aria-label="Log in or create an account">
      <button type="button" role="tab" id="tb-tab-login" aria-selected="true" aria-controls="tb-panel-login">Log in</button>
      <button type="button" role="tab" id="tb-tab-signup" aria-selected="false" aria-controls="tb-panel-signup" tabindex="-1">Create account</button>
    </div>
    <section role="tabpanel" id="tb-panel-login" aria-labelledby="tb-tab-login">
      <h1>Welcome back</h1>
      <p class="tb-sub">Log in to manage your projects.</p>
      <form action="#" method="post" onsubmit="event.preventDefault()">
        <label class="tb-label" for="tb-li-email">Email</label>
        <input class="tb-input" type="email" id="tb-li-email" name="email" placeholder="[email protected]" autocomplete="username" required>
        <label class="tb-label" for="tb-li-password">Password</label>
        <input class="tb-input" type="password" id="tb-li-password" name="password" autocomplete="current-password" required>
        <button class="tb-go" type="submit">Log in</button>
      </form>
      <p class="tb-small"><a href="#">Forgot your password?</a></p>
    </section>
    <section role="tabpanel" id="tb-panel-signup" aria-labelledby="tb-tab-signup" hidden>
      <h1>Create your account</h1>
      <p class="tb-sub">Free for 14 days. No credit card needed.</p>
      <form action="#" method="post" onsubmit="event.preventDefault()">
        <label class="tb-label" for="tb-su-name">Full name</label>
        <input class="tb-input" type="text" id="tb-su-name" name="name" placeholder="Ada Lovelace" autocomplete="name" required>
        <label class="tb-label" for="tb-su-email">Email</label>
        <input class="tb-input" type="email" id="tb-su-email" name="email" placeholder="[email protected]" autocomplete="email" required>
        <label class="tb-label" for="tb-su-password">Password</label>
        <input class="tb-input" type="password" id="tb-su-password" name="new-password" autocomplete="new-password" minlength="8" aria-describedby="tb-su-help" required>
        <p class="tb-help" id="tb-su-help">At least 8 characters.</p>
        <button class="tb-go" type="submit">Create account</button>
      </form>
      <p class="tb-small">By signing up you agree to the <a href="#">Terms</a>.</p>
    </section>
  </div>
</div>
CSS
/* Log in / Create account in one card: an ARIA tablist switches two tab panels, each with its own form. */
.tb{--tb-ink:#134e4a;--tb-teal:#0f766e;--tb-teal-dark:#115e59;--tb-muted:#5f7470;--tb-line:#8e9694;
  min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;background:linear-gradient(160deg,#134e4a,#0f766e 55%,#115e59);
  color:var(--tb-ink);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
.tb h1,.tb p{margin:0}
.tb [hidden]{display:none!important}
.tb-card{width:100%;max-width:400px;background:#fff;border-radius:18px;padding:36px 34px 40px;box-shadow:0 26px 60px -18px rgba(0,0,0,.45)}
.tb-tabs{display:flex;background:#f0fdfa;border:1px solid #ccfbf1;border-radius:12px;padding:5px;margin-bottom:28px}
.tb-tabs button{flex:1;padding:10px;border:0;border-radius:9px;background:transparent;font:inherit;font-size:.9rem;font-weight:700;color:var(--tb-teal);cursor:pointer;
  transition:background-color .15s,color .15s,box-shadow .15s}
.tb-tabs button[aria-selected="true"]{background:var(--tb-teal);color:#fff;box-shadow:0 4px 12px -4px rgba(15,118,110,.5)}
.tb h1{font-size:1.4rem;letter-spacing:-.02em;margin-bottom:4px}
.tb-sub{color:var(--tb-muted);font-size:.9rem;margin-bottom:24px!important}
.tb-label{display:block;font-size:.83rem;font-weight:700;margin-bottom:6px}
.tb-input{display:block;width:100%;padding:12px 14px;margin-bottom:16px;border:1px solid var(--tb-line);border-radius:10px;font:inherit;font-size:.94rem;color:inherit;
  background:#fff;transition:border-color .15s,box-shadow .15s}
.tb-input::placeholder{color:var(--tb-muted)}
.tb-input:focus{outline:none;border-color:var(--tb-teal);box-shadow:0 0 0 3px rgba(15,118,110,.22)}
.tb-input[aria-describedby]{margin-bottom:6px}
.tb-help{font-size:.8rem;color:var(--tb-muted);margin-bottom:16px!important}
.tb-go{width:100%;padding:13px;border:0;border-radius:10px;background:var(--tb-teal);color:#fff;font:inherit;font-weight:800;font-size:.95rem;cursor:pointer;
  transition:background-color .15s;margin-top:4px}
.tb-go:hover{background:var(--tb-teal-dark)}
.tb-small{margin-top:18px!important;font-size:.82rem;color:var(--tb-muted);text-align:center}
.tb-small a{color:var(--tb-teal);font-weight:700;text-decoration:none;border-radius:3px}
.tb-small a:hover{text-decoration:underline}
.tb a:focus-visible,.tb-go:focus-visible,.tb-tabs button:focus-visible{outline:2px solid var(--tb-teal);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.tb-tabs button,.tb-input,.tb-go{transition:none}}
JavaScript
// Accessible tabs: click or use Left / Right / Home / End. Only the selected tab is in the Tab order.
document.querySelectorAll('[role="tablist"]').forEach(function (list) {
  var tabs = Array.prototype.slice.call(list.querySelectorAll('[role="tab"]'));
  function select(tab, focus) {
    tabs.forEach(function (t) {
      var on = t === tab;
      t.setAttribute('aria-selected', String(on));
      t.tabIndex = on ? 0 : -1;
      document.getElementById(t.getAttribute('aria-controls')).hidden = !on;
    });
    if (focus) tab.focus();
  }
  tabs.forEach(function (tab, i) {
    tab.addEventListener('click', function () { select(tab, false); });
    tab.addEventListener('keydown', function (e) {
      var next = { ArrowRight: i + 1, ArrowLeft: i - 1, Home: 0, End: tabs.length - 1 }[e.key];
      if (next === undefined) return;
      e.preventDefault();
      select(tabs[(next + tabs.length) % tabs.length], true);
    });
  });
});

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div class="tb d-flex align-items-center justify-content-center">
  <div class="card w-100">
    <div class="nav nav-pills nav-fill flex-nowrap" role="tablist" aria-label="Log in or create an account">
      <button class="nav-link" type="button" role="tab" id="tb-tab-login" aria-selected="true" aria-controls="tb-panel-login">Log in</button>
      <button class="nav-link" type="button" role="tab" id="tb-tab-signup" aria-selected="false" aria-controls="tb-panel-signup" tabindex="-1">Create account</button>
    </div>
    <section role="tabpanel" id="tb-panel-login" aria-labelledby="tb-tab-login">
      <h1>Welcome back</h1>
      <p class="tb-sub text-body-secondary">Log in to manage your projects.</p>
      <form action="#" method="post" onsubmit="event.preventDefault()">
        <label class="form-label" for="tb-li-email">Email</label>
        <input class="form-control" type="email" id="tb-li-email" name="email" placeholder="[email protected]" autocomplete="username" required>
        <label class="form-label" for="tb-li-password">Password</label>
        <input class="form-control" type="password" id="tb-li-password" name="password" autocomplete="current-password" required>
        <button class="btn btn-tb w-100" type="submit">Log in</button>
      </form>
      <p class="tb-small text-center mb-0"><a href="#">Forgot your password?</a></p>
    </section>
    <section role="tabpanel" id="tb-panel-signup" aria-labelledby="tb-tab-signup" hidden>
      <h1>Create your account</h1>
      <p class="tb-sub text-body-secondary">Free for 14 days. No credit card needed.</p>
      <form action="#" method="post" onsubmit="event.preventDefault()">
        <label class="form-label" for="tb-su-name">Full name</label>
        <input class="form-control" type="text" id="tb-su-name" name="name" placeholder="Ada Lovelace" autocomplete="name" required>
        <label class="form-label" for="tb-su-email">Email</label>
        <input class="form-control" type="email" id="tb-su-email" name="email" placeholder="[email protected]" autocomplete="email" required>
        <label class="form-label" for="tb-su-password">Password</label>
        <input class="form-control" type="password" id="tb-su-password" name="new-password" autocomplete="new-password" minlength="8" aria-describedby="tb-su-help" required>
        <p class="form-text" id="tb-su-help">At least 8 characters.</p>
        <button class="btn btn-tb w-100" type="submit">Create account</button>
      </form>
      <p class="tb-small text-center text-body-secondary mb-0">By signing up you agree to the <a href="#">Terms</a>.</p>
    </section>
  </div>
</div>
CSS
/* Bootstrap .card with .nav-pills as an ARIA tablist, .form-control fields and .form-text for the password rule. */
.tb{--tb-teal:#0f766e;--tb-teal-dark:#115e59;
  --bs-body-color:#134e4a;--bs-secondary-color:#5f7470;--bs-border-color:#8e9694;
  --bs-body-font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  min-height:100vh;padding:24px;background:linear-gradient(160deg,#134e4a,#0f766e 55%,#115e59);color:var(--bs-body-color);
  font-family:var(--bs-body-font-family);line-height:normal}
.tb [hidden]{display:none!important}
.tb .card{--bs-card-border-width:0;--bs-card-border-radius:18px;--bs-card-color:#134e4a;max-width:400px;padding:36px 34px 40px;box-shadow:0 26px 60px -18px rgba(0,0,0,.45)}
.tb .nav-pills{--bs-nav-pills-border-radius:9px;--bs-nav-pills-link-active-bg:var(--tb-teal);--bs-nav-pills-link-active-color:#fff;--bs-nav-link-padding-y:10px;
  --bs-nav-link-font-size:.9rem;--bs-nav-link-font-weight:700;--bs-nav-link-color:var(--tb-teal);--bs-nav-link-hover-color:var(--tb-teal);
  background:#f0fdfa;border:1px solid #ccfbf1;border-radius:12px;padding:5px;margin-bottom:28px}
.tb .nav-pills .nav-link{width:100%;line-height:1.2}
.tb .nav-pills .nav-link[aria-selected="true"]{background:var(--tb-teal);color:#fff;box-shadow:0 4px 12px -4px rgba(15,118,110,.5)}
.tb .nav-pills .nav-link:focus-visible{box-shadow:none;outline:2px solid var(--tb-teal);outline-offset:2px}
.tb h1{font-size:1.4rem;letter-spacing:-.02em;font-weight:700;margin-bottom:4px}
.tb-sub{font-size:.9rem;margin-bottom:24px}
.tb .form-label{font-size:.83rem;font-weight:700;margin-bottom:6px}
.tb .form-control{padding:12px 14px;border-radius:10px;font-size:.94rem;line-height:1.2;margin-bottom:16px}
.tb .form-control[aria-describedby]{margin-bottom:6px}
.tb .form-control::placeholder{color:var(--bs-secondary-color)}
.tb .form-control:focus{border-color:var(--tb-teal);box-shadow:0 0 0 3px rgba(15,118,110,.22)}
.tb .form-text{font-size:.8rem;margin:0 0 16px}
.tb .btn-tb{--bs-btn-bg:var(--tb-teal);--bs-btn-border-color:var(--tb-teal);--bs-btn-color:#fff;--bs-btn-hover-bg:var(--tb-teal-dark);--bs-btn-hover-border-color:var(--tb-teal-dark);
  --bs-btn-hover-color:#fff;--bs-btn-active-bg:var(--tb-teal-dark);--bs-btn-active-border-color:var(--tb-teal-dark);--bs-btn-active-color:#fff;
  --bs-btn-padding-y:13px;--bs-btn-font-size:.95rem;--bs-btn-font-weight:800;--bs-btn-border-radius:10px;--bs-btn-line-height:1.2;--bs-btn-focus-box-shadow:none;margin-top:4px}
.tb-small{margin-top:18px;font-size:.82rem}
.tb-small a{color:var(--tb-teal);font-weight:700;text-decoration:none;border-radius:3px}
.tb-small a:hover{text-decoration:underline}
.tb a:focus-visible,.tb .btn-tb:focus-visible{outline:2px solid var(--tb-teal);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.tb .nav-link,.tb .form-control,.tb .btn{transition:none}}
JavaScript
// Accessible tabs: click or use Left / Right / Home / End. Only the selected tab is in the Tab order.
document.querySelectorAll('[role="tablist"]').forEach(function (list) {
  var tabs = Array.prototype.slice.call(list.querySelectorAll('[role="tab"]'));
  function select(tab, focus) {
    tabs.forEach(function (t) {
      var on = t === tab;
      t.setAttribute('aria-selected', String(on));
      t.tabIndex = on ? 0 : -1;
      document.getElementById(t.getAttribute('aria-controls')).hidden = !on;
    });
    if (focus) tab.focus();
  }
  tabs.forEach(function (tab, i) {
    tab.addEventListener('click', function () { select(tab, false); });
    tab.addEventListener('keydown', function (e) {
      var next = { ArrowRight: i + 1, ArrowLeft: i - 1, Home: 0, End: tabs.length - 1 }[e.key];
      if (next === undefined) return;
      e.preventDefault();
      select(tabs[(next + tabs.length) % tabs.length], true);
    });
  });
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div class="flex min-h-screen items-center justify-center bg-linear-160 from-[#134e4a] via-[#0f766e] via-55% to-[#115e59] p-6 font-[-apple-system,BlinkMacSystemFont,'Segoe_UI',Roboto,Helvetica,Arial,sans-serif] leading-[normal] text-tb-ink">
  <div class="w-full max-w-[400px] rounded-[18px] bg-white px-[34px] pt-9 pb-10 shadow-[0_26px_60px_-18px_rgba(0,0,0,.45)]">
    <div class="mb-7 flex rounded-xl border border-[#ccfbf1] bg-[#f0fdfa] p-[5px]" role="tablist" aria-label="Log in or create an account">
      <button class="flex-1 cursor-pointer rounded-[9px] p-2.5 text-[.9rem] font-bold text-tb-teal transition-[background-color,color,box-shadow] duration-150 aria-selected:bg-tb-teal aria-selected:text-white aria-selected:shadow-[0_4px_12px_-4px_rgba(15,118,110,.5)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tb-teal motion-reduce:transition-none" type="button" role="tab" id="tb-tab-login" aria-selected="true" aria-controls="tb-panel-login">Log in</button>
      <button class="flex-1 cursor-pointer rounded-[9px] p-2.5 text-[.9rem] font-bold text-tb-teal transition-[background-color,color,box-shadow] duration-150 aria-selected:bg-tb-teal aria-selected:text-white aria-selected:shadow-[0_4px_12px_-4px_rgba(15,118,110,.5)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tb-teal motion-reduce:transition-none" type="button" role="tab" id="tb-tab-signup" aria-selected="false" aria-controls="tb-panel-signup" tabindex="-1">Create account</button>
    </div>
    <section role="tabpanel" id="tb-panel-login" aria-labelledby="tb-tab-login">
      <h1 class="mb-1 text-[1.4rem] font-bold tracking-[-.02em]">Welcome back</h1>
      <p class="mb-6 text-[.9rem] text-tb-muted">Log in to manage your projects.</p>
      <form action="#" method="post" onsubmit="event.preventDefault()">
        <label class="mb-1.5 block text-[.83rem] font-bold" for="tb-li-email">Email</label>
        <input class="mb-4 block w-full rounded-[10px] border border-tb-line bg-white px-3.5 py-3 text-[.94rem] transition-[border-color,box-shadow] duration-150 placeholder:text-tb-muted focus:border-tb-teal focus:shadow-[0_0_0_3px_rgba(15,118,110,.22)] focus:outline-none motion-reduce:transition-none" type="email" id="tb-li-email" name="email" placeholder="[email protected]" autocomplete="username" required>
        <label class="mb-1.5 block text-[.83rem] font-bold" for="tb-li-password">Password</label>
        <input class="mb-4 block w-full rounded-[10px] border border-tb-line bg-white px-3.5 py-3 text-[.94rem] transition-[border-color,box-shadow] duration-150 placeholder:text-tb-muted focus:border-tb-teal focus:shadow-[0_0_0_3px_rgba(15,118,110,.22)] focus:outline-none motion-reduce:transition-none" type="password" id="tb-li-password" name="password" autocomplete="current-password" required>
        <button class="mt-1 w-full cursor-pointer rounded-[10px] bg-tb-teal p-[13px] text-[.95rem] font-extrabold text-white transition-colors duration-150 hover:bg-tb-teal-dark focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tb-teal motion-reduce:transition-none" type="submit">Log in</button>
      </form>
      <p class="mt-[18px] text-center text-[.82rem] text-tb-muted"><a class="rounded-[3px] font-bold text-tb-teal hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tb-teal" href="#">Forgot your password?</a></p>
    </section>
    <section role="tabpanel" id="tb-panel-signup" aria-labelledby="tb-tab-signup" hidden>
      <h1 class="mb-1 text-[1.4rem] font-bold tracking-[-.02em]">Create your account</h1>
      <p class="mb-6 text-[.9rem] text-tb-muted">Free for 14 days. No credit card needed.</p>
      <form action="#" method="post" onsubmit="event.preventDefault()">
        <label class="mb-1.5 block text-[.83rem] font-bold" for="tb-su-name">Full name</label>
        <input class="mb-4 block w-full rounded-[10px] border border-tb-line bg-white px-3.5 py-3 text-[.94rem] transition-[border-color,box-shadow] duration-150 placeholder:text-tb-muted focus:border-tb-teal focus:shadow-[0_0_0_3px_rgba(15,118,110,.22)] focus:outline-none motion-reduce:transition-none" type="text" id="tb-su-name" name="name" placeholder="Ada Lovelace" autocomplete="name" required>
        <label class="mb-1.5 block text-[.83rem] font-bold" for="tb-su-email">Email</label>
        <input class="mb-4 block w-full rounded-[10px] border border-tb-line bg-white px-3.5 py-3 text-[.94rem] transition-[border-color,box-shadow] duration-150 placeholder:text-tb-muted focus:border-tb-teal focus:shadow-[0_0_0_3px_rgba(15,118,110,.22)] focus:outline-none motion-reduce:transition-none" type="email" id="tb-su-email" name="email" placeholder="[email protected]" autocomplete="email" required>
        <label class="mb-1.5 block text-[.83rem] font-bold" for="tb-su-password">Password</label>
        <input class="mb-1.5 block w-full rounded-[10px] border border-tb-line bg-white px-3.5 py-3 text-[.94rem] transition-[border-color,box-shadow] duration-150 placeholder:text-tb-muted focus:border-tb-teal focus:shadow-[0_0_0_3px_rgba(15,118,110,.22)] focus:outline-none motion-reduce:transition-none" type="password" id="tb-su-password" name="new-password" autocomplete="new-password" minlength="8" aria-describedby="tb-su-help" required>
        <p class="mb-4 text-[.8rem] text-tb-muted" id="tb-su-help">At least 8 characters.</p>
        <button class="mt-1 w-full cursor-pointer rounded-[10px] bg-tb-teal p-[13px] text-[.95rem] font-extrabold text-white transition-colors duration-150 hover:bg-tb-teal-dark focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tb-teal motion-reduce:transition-none" type="submit">Create account</button>
      </form>
      <p class="mt-[18px] text-center text-[.82rem] text-tb-muted">By signing up you agree to the <a class="rounded-[3px] font-bold text-tb-teal hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tb-teal" href="#">Terms</a>.</p>
    </section>
  </div>
</div>
CSS
@theme {
  --color-tb-ink: #134e4a;
  --color-tb-teal: #0f766e;
  --color-tb-teal-dark: #115e59;
  --color-tb-muted: #5f7470;
  --color-tb-line: #8e9694;
}
JavaScript
// Accessible tabs: click or use Left / Right / Home / End. Only the selected tab is in the Tab order.
document.querySelectorAll('[role="tablist"]').forEach(function (list) {
  var tabs = Array.prototype.slice.call(list.querySelectorAll('[role="tab"]'));
  function select(tab, focus) {
    tabs.forEach(function (t) {
      var on = t === tab;
      t.setAttribute('aria-selected', String(on));
      t.tabIndex = on ? 0 : -1;
      document.getElementById(t.getAttribute('aria-controls')).hidden = !on;
    });
    if (focus) tab.focus();
  }
  tabs.forEach(function (tab, i) {
    tab.addEventListener('click', function () { select(tab, false); });
    tab.addEventListener('keydown', function (e) {
      var next = { ArrowRight: i + 1, ArrowLeft: i - 1, Home: 0, End: tabs.length - 1 }[e.key];
      if (next === undefined) return;
      e.preventDefault();
      select(tabs[(next + tabs.length) % tabs.length], true);
    });
  });
});

About this set

One white card on a deep teal gradient that holds both forms. A pill-shaped tab bar at the top switches between Log in and Create account. The login panel asks for email and password and links to password recovery; the sign-up panel asks for full name, email and a new password, shows an At least 8 characters hint under the password field, and links to the terms. The tabs follow the ARIA tabs pattern: a tablist with two tab buttons, each controlling a tabpanel, with aria-selected on the active tab. A short script handles clicks and the Left, Right, Home and End keys, and only the selected tab is in the Tab order, so keyboard users move straight from the tabs into the form. Use it for products where new and returning users arrive at the same page. The sign-up password uses autocomplete=”new-password” and minlength=”8″, and its hint is linked with aria-describedby so it is read with the field. The Bootstrap version builds the tab bar from .nav-pills and uses .form-text for the hint; the Tailwind version styles the active tab with aria-selected: utilities.

What’s included

  • ARIA tablist with arrow key, Home and End support
  • Separate login and sign-up forms in one card
  • Password rule shown as visible hint linked with aria-describedby
  • autocomplete values for name, username, email and new-password
  • Bootstrap version built on .nav-pills

Accessibility

Tabs expose role, selected state and the panel they control, and each panel is labelled by its tab. Arrow keys move between tabs and switch panels. Every field has a visible label, and the new password hint is announced with the field. Tabs, buttons and links show a 2px teal outline on keyboard focus; transitions switch off under prefers-reduced-motion.

Customise it

Change --tb-teal, --tb-teal-dark and --tb-line on .tb. In Bootstrap the tab colours are --bs-nav-pills-* variables on .nav-pills; in Tailwind edit the --color-tb-* theme colours.