Open demo

CSS code

HTML
<div class="nb">
  <form class="nb-box" action="#" method="post" onsubmit="event.preventDefault()">
    <span class="nb-tag">Members only</span>
    <h1>Log in.</h1>
    <p class="nb-sub">No fluff. Just your inbox and your work.</p>
    <label class="nb-label" for="nb-email">Email</label>
    <input class="nb-input" type="email" id="nb-email" name="email" placeholder="[email protected]" autocomplete="username" required>
    <label class="nb-label" for="nb-password">Password</label>
    <input class="nb-input" type="password" id="nb-password" name="password" placeholder="Top secret" autocomplete="current-password" required>
    <button class="nb-btn" type="submit">Let me in <span aria-hidden="true">→</span></button>
    <div class="nb-links">
      <a href="#">Lost password</a>
      <a href="#">Join instead</a>
    </div>
  </form>
</div>
CSS
/* Neobrutalist login: 3px black borders, hard offset shadows, and controls that press into the page. */
.nb{--nb-ink:#111;--nb-yellow:#ffde59;--nb-violet:#a78bfa;--nb-green:#4ade80;
  min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;background:var(--nb-yellow);
  background-image:radial-gradient(#00000012 1.5px,transparent 1.5px);background-size:22px 22px;color:var(--nb-ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
.nb h1,.nb p{margin:0}
.nb-box{width:100%;max-width:400px;background:#fff;border:3px solid var(--nb-ink);border-radius:14px;box-shadow:8px 8px 0 var(--nb-ink);padding:38px 34px}
.nb-tag{display:inline-block;background:var(--nb-violet);border:3px solid var(--nb-ink);border-radius:8px;font-weight:800;font-size:.75rem;letter-spacing:.05em;
  padding:5px 10px;box-shadow:3px 3px 0 var(--nb-ink);margin-bottom:18px;text-transform:uppercase}
.nb h1{font-size:1.8rem;font-weight:900;letter-spacing:-.03em;margin-bottom:6px}
.nb-sub{font-size:.92rem;font-weight:600;color:#444;margin-bottom:26px!important}
.nb-label{display:block;font-size:.85rem;font-weight:800;margin-bottom:6px;text-transform:uppercase;letter-spacing:.03em}
.nb-input{display:block;width:100%;padding:12px 14px;margin-bottom:18px;border:3px solid var(--nb-ink);border-radius:10px;background:#fff;color:inherit;
  font:inherit;font-size:.95rem;font-weight:600;transition:box-shadow .12s,transform .12s}
.nb-input::placeholder{color:#666}
.nb-input:focus{outline:none;box-shadow:4px 4px 0 var(--nb-ink);transform:translate(-2px,-2px)}
.nb-btn{width:100%;padding:14px;border:3px solid var(--nb-ink);border-radius:10px;background:var(--nb-green);color:var(--nb-ink);font:inherit;font-size:1rem;
  font-weight:900;text-transform:uppercase;letter-spacing:.04em;cursor:pointer;box-shadow:5px 5px 0 var(--nb-ink);transition:box-shadow .12s,transform .12s}
.nb-btn:hover{transform:translate(2px,2px);box-shadow:2px 2px 0 var(--nb-ink)}
.nb-btn:active{transform:translate(5px,5px);box-shadow:0 0 0 var(--nb-ink)}
.nb-links{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-top:22px;font-size:.85rem;font-weight:800}
.nb-links a{color:var(--nb-ink);text-decoration:underline;text-decoration-thickness:3px;text-underline-offset:3px;text-decoration-color:var(--nb-violet)}
.nb-links a:hover{text-decoration-color:var(--nb-green)}
.nb a:focus-visible,.nb-btn:focus-visible{outline:3px solid var(--nb-ink);outline-offset:3px;border-radius:4px}
.nb-btn:focus-visible{border-radius:10px}
@media (prefers-reduced-motion:reduce){.nb-input,.nb-btn{transition:none}.nb-input:focus,.nb-btn:hover,.nb-btn:active{transform:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div class="nb d-flex align-items-center justify-content-center">
  <form class="card w-100" action="#" method="post" onsubmit="event.preventDefault()">
    <div class="card-body">
      <span class="badge text-uppercase">Members only</span>
      <h1>Log in.</h1>
      <p class="nb-sub">No fluff. Just your inbox and your work.</p>
      <div class="nb-field">
        <label class="form-label text-uppercase" for="nb-email">Email</label>
        <input class="form-control" type="email" id="nb-email" name="email" placeholder="[email protected]" autocomplete="username" required>
      </div>
      <div class="nb-field">
        <label class="form-label text-uppercase" for="nb-password">Password</label>
        <input class="form-control" type="password" id="nb-password" name="password" placeholder="Top secret" autocomplete="current-password" required>
      </div>
      <button class="btn btn-nb w-100 text-uppercase" type="submit">Let me in <span aria-hidden="true">→</span></button>
      <div class="nb-links d-flex flex-wrap justify-content-between gap-3">
        <a href="#">Lost password</a>
        <a href="#">Join instead</a>
      </div>
    </div>
  </form>
</div>
CSS
/* Bootstrap .card, .badge, .form-control and .btn given 3px black borders and hard offset shadows. */
.nb{--nb-ink:#111;--nb-violet:#a78bfa;--nb-green:#4ade80;
  --bs-body-color:#111;--bs-border-color:#111;--bs-border-width:3px;
  --bs-body-font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  min-height:100vh;padding:24px;background:#ffde59;background-image:radial-gradient(#00000012 1.5px,transparent 1.5px);background-size:22px 22px;
  color:var(--bs-body-color);font-family:var(--bs-body-font-family);line-height:normal}
.nb .card{--bs-card-border-width:3px;--bs-card-border-color:var(--nb-ink);--bs-card-border-radius:14px;--bs-card-spacer-y:38px;--bs-card-spacer-x:34px;
  max-width:400px;box-shadow:8px 8px 0 var(--nb-ink)}
.nb .badge{--bs-badge-font-size:.75rem;--bs-badge-font-weight:800;--bs-badge-padding-x:10px;--bs-badge-padding-y:5px;--bs-badge-color:var(--nb-ink);
  --bs-badge-border-radius:8px;background:var(--nb-violet);border:3px solid var(--nb-ink);letter-spacing:.05em;box-shadow:3px 3px 0 var(--nb-ink);margin-bottom:18px}
.nb h1{font-size:1.8rem;font-weight:900;letter-spacing:-.03em;margin-bottom:6px}
.nb-sub{font-size:.92rem;font-weight:600;color:#444;margin-bottom:26px}
.nb .form-label{font-size:.85rem;font-weight:800;margin-bottom:6px;letter-spacing:.03em}
.nb .form-control{padding:12px 14px;border-radius:10px;font-size:.95rem;font-weight:600;line-height:1.2;transition:box-shadow .12s,transform .12s}
.nb .form-control::placeholder{color:#666}
.nb .form-control:focus{border-color:var(--nb-ink);box-shadow:4px 4px 0 var(--nb-ink);transform:translate(-2px,-2px)}
.nb-field{margin-bottom:18px}
.nb .btn-nb{--bs-btn-bg:var(--nb-green);--bs-btn-border-color:var(--nb-ink);--bs-btn-color:var(--nb-ink);--bs-btn-hover-bg:var(--nb-green);
  --bs-btn-hover-border-color:var(--nb-ink);--bs-btn-hover-color:var(--nb-ink);--bs-btn-active-bg:var(--nb-green);--bs-btn-active-border-color:var(--nb-ink);
  --bs-btn-active-color:var(--nb-ink);--bs-btn-border-width:3px;--bs-btn-padding-y:14px;--bs-btn-font-size:1rem;--bs-btn-font-weight:900;
  --bs-btn-border-radius:10px;--bs-btn-line-height:1.2;--bs-btn-focus-box-shadow:5px 5px 0 var(--nb-ink);letter-spacing:.04em;box-shadow:5px 5px 0 var(--nb-ink);
  transition:box-shadow .12s,transform .12s}
.nb .btn-nb:hover{transform:translate(2px,2px);box-shadow:2px 2px 0 var(--nb-ink)}
.nb .btn-nb:active{transform:translate(5px,5px);box-shadow:0 0 0 var(--nb-ink)}
.nb-links{margin-top:22px;font-size:.85rem;font-weight:800}
.nb-links a{color:var(--nb-ink);text-decoration:underline;text-decoration-thickness:3px;text-underline-offset:3px;text-decoration-color:var(--nb-violet)}
.nb-links a:hover{text-decoration-color:var(--nb-green)}
.nb a:focus-visible,.nb .btn-nb:focus-visible{outline:3px solid var(--nb-ink);outline-offset:3px;border-radius:4px}
.nb .btn-nb:focus-visible{border-radius:10px}
@media (prefers-reduced-motion:reduce){.nb .form-control,.nb .btn-nb{transition:none}.nb .form-control:focus,.nb .btn-nb:hover,.nb .btn-nb:active{transform:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div class="flex min-h-screen items-center justify-center bg-nb-yellow bg-[radial-gradient(#00000012_1.5px,transparent_1.5px)] bg-size-[22px_22px] p-6 font-[-apple-system,BlinkMacSystemFont,'Segoe_UI',Roboto,Helvetica,Arial,sans-serif] leading-[normal] text-nb-ink">
  <form class="w-full max-w-[400px] rounded-[14px] border-3 border-nb-ink bg-white px-[34px] py-[38px] shadow-[8px_8px_0_var(--color-nb-ink)]" action="#" method="post" onsubmit="event.preventDefault()">
    <span class="mb-[18px] inline-block rounded-lg border-3 border-nb-ink bg-nb-violet px-2.5 py-[5px] text-xs font-extrabold tracking-[.05em] uppercase shadow-[3px_3px_0_var(--color-nb-ink)]">Members only</span>
    <h1 class="mb-1.5 text-[1.8rem] font-black tracking-[-.03em]">Log in.</h1>
    <p class="mb-[26px] text-[.92rem] font-semibold text-[#444]">No fluff. Just your inbox and your work.</p>
    <label class="mb-1.5 block text-[.85rem] font-extrabold tracking-[.03em] uppercase" for="nb-email">Email</label>
    <input class="mb-[18px] block w-full rounded-[10px] border-3 border-nb-ink bg-white px-3.5 py-3 text-[.95rem] font-semibold transition-[box-shadow,transform] duration-[120ms] placeholder:text-[#666] focus:-translate-x-0.5 focus:-translate-y-0.5 focus:shadow-[4px_4px_0_var(--color-nb-ink)] focus:outline-none motion-reduce:transition-none motion-reduce:focus:translate-none" type="email" id="nb-email" name="email" placeholder="[email protected]" autocomplete="username" required>
    <label class="mb-1.5 block text-[.85rem] font-extrabold tracking-[.03em] uppercase" for="nb-password">Password</label>
    <input class="mb-[18px] block w-full rounded-[10px] border-3 border-nb-ink bg-white px-3.5 py-3 text-[.95rem] font-semibold transition-[box-shadow,transform] duration-[120ms] placeholder:text-[#666] focus:-translate-x-0.5 focus:-translate-y-0.5 focus:shadow-[4px_4px_0_var(--color-nb-ink)] focus:outline-none motion-reduce:transition-none motion-reduce:focus:translate-none" type="password" id="nb-password" name="password" placeholder="Top secret" autocomplete="current-password" required>
    <button class="w-full cursor-pointer rounded-[10px] border-3 border-nb-ink bg-nb-green p-3.5 text-base font-black tracking-[.04em] uppercase shadow-[5px_5px_0_var(--color-nb-ink)] transition-[box-shadow,transform] duration-[120ms] hover:translate-x-0.5 hover:translate-y-0.5 hover:shadow-[2px_2px_0_var(--color-nb-ink)] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-nb-ink active:translate-x-[5px] active:translate-y-[5px] active:shadow-none motion-reduce:transition-none motion-reduce:hover:translate-none motion-reduce:active:translate-none" type="submit">Let me in <span aria-hidden="true">→</span></button>
    <div class="mt-[22px] flex flex-wrap justify-between gap-3 text-[.85rem] font-extrabold">
      <a class="rounded underline decoration-nb-violet decoration-3 underline-offset-3 hover:decoration-nb-green focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-nb-ink" href="#">Lost password</a>
      <a class="rounded underline decoration-nb-violet decoration-3 underline-offset-3 hover:decoration-nb-green focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-nb-ink" href="#">Join instead</a>
    </div>
  </form>
</div>
CSS
@theme {
  --color-nb-ink: #111;
  --color-nb-yellow: #ffde59;
  --color-nb-violet: #a78bfa;
  --color-nb-green: #4ade80;
}

About this set

A loud, flat sign-in card on a yellow dotted background: 3 pixel black borders, hard offset shadows with no blur, a violet Members only tag, a heavy Log in. heading and uppercase field labels. When an input is focused it lifts up and to the left and gains its own black shadow; the green Let me in button sinks towards its shadow on hover and presses flat when clicked. The links underneath use thick violet underlines that turn green on hover. Use it for indie products, portfolios, zines and developer tools that want personality rather than polish. All of the motion is done with transform and box-shadow transitions of 120 milliseconds, and it is switched off under prefers-reduced-motion so fields and buttons stay still. The arrow in the button is hidden from screen readers so it is announced simply as Let me in. The Bootstrap version gives .card, .badge, .form-control and .btn the same borders and shadows through Bootstrap variables; the Tailwind version uses border-3 and shadow-[…] utilities with a theme colour for the ink.

What’s included

  • 3px black borders and hard offset shadows throughout
  • Fields lift on focus; the button presses into its shadow
  • All motion removed under prefers-reduced-motion
  • Thick coloured underlines on the footer links
  • High-contrast palette that passes WCAG AA as designed

Accessibility

Labels are visible and uppercase through CSS, so the underlying text stays normal case for screen readers. Focused fields are marked by their shadow and shift; links and the button show a 3px black outline on keyboard focus. The decorative arrow is aria-hidden, and transforms and transitions are off under prefers-reduced-motion.

Customise it

Change --nb-yellow, --nb-violet and --nb-green on .nb, and the 8px or 5px shadow offsets. In Tailwind edit the --color-nb-* theme colours and the shadow-[...] utilities.