Open demo

CSS code

HTML
<div class="demo-grid">
<div><span class="lbl">Providers first</span>
<div class="so">
  <div class="so-brand"><span class="so-mark"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l7 7-7 11-7-11z"/><path d="M12 3v18"/></svg></span>Kitepost</div>
  <h2 class="so-title" id="kp-title">Start your newsletter</h2>
  <p class="so-sub">Publish to email and the web. Free up to 1,000 subscribers.</p>
  <div class="so-providers">
    <a class="so-provider" href="#"><span class="so-tile" aria-hidden="true">G</span>Continue with Google</a>
    <a class="so-provider" href="#"><span class="so-tile" aria-hidden="true">A</span>Continue with Apple</a>
    <a class="so-provider" href="#"><span class="so-tile" aria-hidden="true">M</span>Continue with Microsoft</a>
  </div>
  <p class="so-or">or sign up with email</p>
  <form action="#" method="post" aria-labelledby="kp-title">
    <div class="so-field">
      <label class="so-label" for="kp-name">Name <span class="so-req" aria-hidden="true">*</span></label>
      <input class="so-input" id="kp-name" name="name" type="text" autocomplete="name" required>
    </div>
    <div class="so-field">
      <label class="so-label" for="kp-email">Email <span class="so-req" aria-hidden="true">*</span></label>
      <input class="so-input" id="kp-email" name="email" type="email" autocomplete="email" required>
    </div>
    <div class="so-field">
      <label class="so-label" for="kp-pw">Password <span class="so-req" aria-hidden="true">*</span></label>
      <input class="so-input" id="kp-pw" name="password" type="password" autocomplete="new-password" minlength="8" required aria-describedby="kp-pw-hint">
      <p class="so-hint" id="kp-pw-hint">At least 8 characters. Fields marked * are required.</p>
    </div>
    <button class="so-btn" type="submit">Create account</button>
  </form>
  <p class="so-foot">Already on Kitepost? <a href="#">Log in</a></p>
</div>
</div>
<div><span class="lbl">Email first, icon row</span>
<div class="so so--green">
  <div class="so-brand"><span class="so-mark"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 21V11"/><path d="M12 11C12 7 9 4 4 4c0 5 3 7 8 7zM12 13c0-3 2.5-6 8-6 0 4.5-3 6-8 6z"/></svg></span>Sprigly</div>
  <h2 class="so-title" id="sg-title">Never forget to water again</h2>
  <p class="so-sub">Care reminders for every plant in your home.</p>
  <form action="#" method="post" aria-labelledby="sg-title">
    <div class="so-field">
      <label class="so-label" for="sg-email">Email address <span class="so-req" aria-hidden="true">*</span></label>
      <input class="so-input" id="sg-email" name="email" type="email" autocomplete="email" required aria-describedby="sg-email-hint">
      <p class="so-hint" id="sg-email-hint">Required. We'll email you a link to finish signing up.</p>
    </div>
    <button class="so-btn" type="submit">Continue with email</button>
  </form>
  <p class="so-or">or sign up with</p>
  <div class="so-icons">
    <a class="so-icon" href="#" aria-label="Sign up with Google"><span class="so-tile" aria-hidden="true">G</span>Google</a>
    <a class="so-icon" href="#" aria-label="Sign up with Apple"><span class="so-tile" aria-hidden="true">A</span>Apple</a>
    <a class="so-icon" href="#" aria-label="Sign up with Facebook"><span class="so-tile" aria-hidden="true">F</span>Facebook</a>
  </div>
  <p class="so-terms">By continuing you agree to Sprigly's <a href="#">Terms</a> and <a href="#">Privacy Policy</a>.</p>
</div>
</div>
</div>
CSS
/* Social and email sign-up. Provider buttons are links that would start each provider's sign-in flow; they show
   a neutral letter tile instead of a logo, so swap in each provider's official button when you go live. No JavaScript. */
.so{--so-accent:#6d28d9;--so-accent-dark:#5b21b6;--so-ring:rgba(109,40,217,.22);--so-ink:#1f1b2e;--so-muted:#57536a;--so-line:#85819a;--so-tile:#ece9f5;--so-error:#b91c1c;
  background:#fff;color:var(--so-ink);border-radius:20px;padding:34px 30px 28px;font-size:.92rem;line-height:1.45;
  box-shadow:0 1px 2px rgba(31,27,46,.06),0 16px 36px -16px rgba(46,16,101,.28)}
.so-brand{display:flex;align-items:center;justify-content:center;gap:10px;font-weight:700;margin-bottom:18px}
.so-mark{width:34px;height:34px;border-radius:10px;background:var(--so-accent);color:#fff;display:grid;place-items:center}
.so-title{font-size:1.45rem;font-weight:750;letter-spacing:-.02em;line-height:1.2;text-align:center}
.so-sub{color:var(--so-muted);margin:6px 0 22px;text-align:center}
/* full-width provider buttons */
.so-providers{display:grid;gap:10px}
.so-provider{display:flex;align-items:center;justify-content:center;gap:10px;position:relative;min-height:46px;padding:10px 14px;border:1px solid var(--so-line);
  border-radius:10px;background:#fff;color:var(--so-ink);font-weight:600;text-decoration:none;transition:background-color .15s,border-color .15s}
.so-provider:hover{background:#faf9fd;border-color:var(--so-ink)}
.so-provider:focus-visible{outline:2px solid var(--so-accent);outline-offset:2px}
.so-tile{display:grid;place-items:center;width:24px;height:24px;border-radius:6px;background:var(--so-tile);color:var(--so-ink);font-size:.74rem;font-weight:800}
.so-providers .so-tile{position:absolute;left:12px;top:50%;transform:translateY(-50%)}
/* "or" divider */
.so-or{display:flex;align-items:center;gap:12px;margin:22px 0;color:var(--so-muted);font-size:.8rem}
.so-or::before,.so-or::after{content:"";flex:1;height:1px;background:#d7d4e2}
.so-field{margin-bottom:16px}
.so-label{display:block;font-size:.84rem;font-weight:600;margin-bottom:6px}
.so-req{color:var(--so-accent);font-weight:700}
.so-input{display:block;width:100%;font:inherit;color:inherit;background:#fff;border:1px solid var(--so-line);border-radius:10px;padding:11px 13px;
  transition:border-color .15s,box-shadow .15s}
.so-input:focus{outline:none;border-color:var(--so-accent);box-shadow:0 0 0 3px var(--so-ring)}
.so-input:user-invalid{border-color:var(--so-error)}
.so-hint{font-size:.8rem;color:var(--so-muted);margin-top:6px}
.so-btn{display:block;width:100%;font:inherit;font-weight:600;color:#fff;background:var(--so-accent);border:0;border-radius:10px;padding:12px 16px;cursor:pointer;
  margin-top:4px;transition:background-color .15s}
.so-btn:hover{background:var(--so-accent-dark)}
.so-btn:focus-visible{outline:2px solid var(--so-accent);outline-offset:3px}
.so a:not(.so-provider):not(.so-icon){color:var(--so-accent);text-decoration:underline;text-underline-offset:2px}
.so a:not(.so-provider):not(.so-icon):focus-visible{outline:2px solid var(--so-accent);outline-offset:2px;border-radius:3px}
.so-terms{font-size:.78rem;color:var(--so-muted);margin-top:16px;text-align:center}
.so-foot{margin-top:14px;text-align:center;color:var(--so-muted);font-size:.86rem}
/* icon row of square provider buttons */
.so-icons{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.so-icon{display:flex;flex-direction:column;align-items:center;gap:6px;padding:12px 6px 10px;border:1px solid var(--so-line);border-radius:12px;background:#fff;
  color:var(--so-ink);font-size:.78rem;font-weight:600;text-decoration:none;transition:background-color .15s,border-color .15s}
.so-icon .so-tile{width:30px;height:30px;border-radius:8px;font-size:.86rem}
.so-icon:hover{background:#faf9fd;border-color:var(--so-ink)}
.so-icon:focus-visible{outline:2px solid var(--so-accent);outline-offset:2px}
.so--green{--so-accent:#15803d;--so-accent-dark:#166534;--so-ring:rgba(21,128,61,.22);--so-tile:#e7f3eb}
@media (max-width:420px){.so{padding:26px 20px 22px}}
@media (prefers-reduced-motion:reduce){.so-provider,.so-input,.so-btn,.so-icon{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div class="demo-grid">
<div><span class="lbl">Providers first</span>
<div class="card so">
  <div class="so-brand"><span class="so-mark"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l7 7-7 11-7-11z"/><path d="M12 3v18"/></svg></span>Kitepost</div>
  <h2 class="so-title" id="kp-title">Start your newsletter</h2>
  <p class="so-sub">Publish to email and the web. Free up to 1,000 subscribers.</p>
  <div class="d-grid gap-2">
    <a class="btn so-provider" href="#"><span class="so-tile" aria-hidden="true">G</span>Continue with Google</a>
    <a class="btn so-provider" href="#"><span class="so-tile" aria-hidden="true">A</span>Continue with Apple</a>
    <a class="btn so-provider" href="#"><span class="so-tile" aria-hidden="true">M</span>Continue with Microsoft</a>
  </div>
  <p class="so-or">or sign up with email</p>
  <form action="#" method="post" aria-labelledby="kp-title">
    <div class="mb-3">
      <label class="form-label" for="kp-name">Name <span class="so-req" aria-hidden="true">*</span></label>
      <input class="form-control" id="kp-name" name="name" type="text" autocomplete="name" required>
    </div>
    <div class="mb-3">
      <label class="form-label" for="kp-email">Email <span class="so-req" aria-hidden="true">*</span></label>
      <input class="form-control" id="kp-email" name="email" type="email" autocomplete="email" required>
    </div>
    <div class="mb-3">
      <label class="form-label" for="kp-pw">Password <span class="so-req" aria-hidden="true">*</span></label>
      <input class="form-control" id="kp-pw" name="password" type="password" autocomplete="new-password" minlength="8" required aria-describedby="kp-pw-hint">
      <p class="form-text" id="kp-pw-hint">At least 8 characters. Fields marked * are required.</p>
    </div>
    <button class="btn btn-primary w-100" type="submit">Create account</button>
  </form>
  <p class="so-foot">Already on Kitepost? <a href="#">Log in</a></p>
</div>
</div>
<div><span class="lbl">Email first, icon row</span>
<div class="card so so--green">
  <div class="so-brand"><span class="so-mark"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 21V11"/><path d="M12 11C12 7 9 4 4 4c0 5 3 7 8 7zM12 13c0-3 2.5-6 8-6 0 4.5-3 6-8 6z"/></svg></span>Sprigly</div>
  <h2 class="so-title" id="sg-title">Never forget to water again</h2>
  <p class="so-sub">Care reminders for every plant in your home.</p>
  <form action="#" method="post" aria-labelledby="sg-title">
    <div class="mb-3">
      <label class="form-label" for="sg-email">Email address <span class="so-req" aria-hidden="true">*</span></label>
      <input class="form-control" id="sg-email" name="email" type="email" autocomplete="email" required aria-describedby="sg-email-hint">
      <p class="form-text" id="sg-email-hint">Required. We'll email you a link to finish signing up.</p>
    </div>
    <button class="btn btn-primary w-100" type="submit">Continue with email</button>
  </form>
  <p class="so-or">or sign up with</p>
  <div class="row g-2">
    <div class="col-4"><a class="btn so-icon" href="#" aria-label="Sign up with Google"><span class="so-tile" aria-hidden="true">G</span>Google</a></div>
    <div class="col-4"><a class="btn so-icon" href="#" aria-label="Sign up with Apple"><span class="so-tile" aria-hidden="true">A</span>Apple</a></div>
    <div class="col-4"><a class="btn so-icon" href="#" aria-label="Sign up with Facebook"><span class="so-tile" aria-hidden="true">F</span>Facebook</a></div>
  </div>
  <p class="so-terms">By continuing you agree to Sprigly's <a href="#">Terms</a> and <a href="#">Privacy Policy</a>.</p>
</div>
</div>
</div>
CSS
/* Bootstrap .card, .btn, .form-control and .row, recoloured through Bootstrap's CSS variables. Provider buttons are
   links that would start each provider's sign-in flow; they show a neutral letter tile instead of a logo, so swap in
   each provider's official button when you go live. No JavaScript. */
.so{--so-accent:#6d28d9;--so-accent-dark:#5b21b6;--so-ring:rgba(109,40,217,.22);--so-ink:#1f1b2e;--so-muted:#57536a;--so-line:#85819a;--so-tile:#ece9f5;--so-error:#b91c1c;
  --bs-card-border-width:0;--bs-card-border-radius:20px;--bs-border-color:var(--so-line);--bs-border-radius:10px;--bs-body-color:var(--so-ink);
  --bs-link-color-rgb:109,40,217;--bs-link-hover-color-rgb:91,33,182;
  padding:34px 30px 28px;color:var(--so-ink);font-size:.92rem;line-height:1.45;box-shadow:0 1px 2px rgba(31,27,46,.06),0 16px 36px -16px rgba(46,16,101,.28)}
.so--green{--so-accent:#15803d;--so-accent-dark:#166534;--so-ring:rgba(21,128,61,.22);--so-tile:#e7f3eb;--bs-link-color-rgb:21,128,61;--bs-link-hover-color-rgb:22,101,52}
.so p,.so h2{margin:0}
.so .so-brand{display:flex;align-items:center;justify-content:center;gap:10px;font-weight:700;margin-bottom:18px}
.so .so-mark{width:34px;height:34px;border-radius:10px;background:var(--so-accent);color:#fff;display:grid;place-items:center}
.so .so-title{font-size:1.45rem;font-weight:750;letter-spacing:-.02em;line-height:1.2;text-align:center}
.so .so-sub{color:var(--so-muted);margin:6px 0 22px;text-align:center}
/* provider buttons: .btn restyled as white outline buttons */
.so .so-provider,.so .so-icon{--bs-btn-color:var(--so-ink);--bs-btn-bg:#fff;--bs-btn-border-color:var(--so-line);--bs-btn-hover-color:var(--so-ink);
  --bs-btn-hover-bg:#faf9fd;--bs-btn-hover-border-color:var(--so-ink);--bs-btn-active-bg:#f3f1fa;--bs-btn-active-border-color:var(--so-ink);--bs-btn-active-color:var(--so-ink);
  --bs-btn-font-weight:600;--bs-btn-font-size:.92rem;--bs-btn-border-radius:10px;--bs-btn-focus-box-shadow:none;line-height:1.45}
.so .so-provider{display:flex;align-items:center;justify-content:center;position:relative;min-height:46px;padding:10px 14px}
.so .so-provider:focus-visible,.so .so-icon:focus-visible{outline:2px solid var(--so-accent);outline-offset:2px}
.so .so-tile{display:grid;place-items:center;width:24px;height:24px;border-radius:6px;background:var(--so-tile);color:var(--so-ink);font-size:.74rem;font-weight:800}
.so .so-provider .so-tile{position:absolute;left:12px;top:50%;transform:translateY(-50%)}
.so .so-icon{--bs-btn-font-size:.78rem;--bs-btn-border-radius:12px;display:flex;flex-direction:column;align-items:center;gap:6px;width:100%;padding:12px 6px 10px}
.so .so-icon .so-tile{width:30px;height:30px;border-radius:8px;font-size:.86rem}
/* "or" divider */
.so .so-or{display:flex;align-items:center;gap:12px;margin:22px 0;color:var(--so-muted);font-size:.8rem}
.so .so-or::before,.so .so-or::after{content:"";flex:1;height:1px;background:#d7d4e2}
.so .form-label{display:block;font-size:.84rem;font-weight:600;margin-bottom:6px}
.so .so-req{color:var(--so-accent);font-weight:700}
.so .form-control{font-size:inherit;line-height:inherit;color:var(--so-ink);padding:11px 13px;transition:border-color .15s,box-shadow .15s}
.so .form-control:focus{border-color:var(--so-accent);box-shadow:0 0 0 3px var(--so-ring)}
.so .form-control:user-invalid{border-color:var(--so-error)}
.so .form-text{font-size:.8rem;color:var(--so-muted);margin-top:6px}
.so .btn-primary{--bs-btn-bg:var(--so-accent);--bs-btn-border-color:var(--so-accent);--bs-btn-hover-bg:var(--so-accent-dark);--bs-btn-hover-border-color:var(--so-accent-dark);
  --bs-btn-active-bg:var(--so-accent-dark);--bs-btn-active-border-color:var(--so-accent-dark);--bs-btn-focus-box-shadow:none;
  --bs-btn-font-weight:600;--bs-btn-padding-y:11px;--bs-btn-font-size:.92rem;--bs-btn-border-radius:10px;line-height:1.45;margin-top:4px;display:block}
.so .btn-primary:focus-visible{outline:2px solid var(--so-accent);outline-offset:3px}
.so a:not(.btn){text-underline-offset:2px}
.so a:not(.btn):focus-visible{outline:2px solid var(--so-accent);outline-offset:2px;border-radius:3px}
.so .so-terms{font-size:.78rem;color:var(--so-muted);margin-top:16px;text-align:center}
.so .so-foot{margin-top:14px;text-align:center;color:var(--so-muted);font-size:.86rem}
.card.so{display:block} /* plain block flow, so vertical margins match the CSS version */
@media (max-width:420px){.so{padding:26px 20px 22px}}
@media (prefers-reduced-motion:reduce){.so .btn,.so .form-control{transition:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div class="grid grid-cols-[repeat(auto-fit,minmax(300px,1fr))] items-start gap-[34px]">
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#5f5a70] uppercase">Providers first</span>
<div class="rounded-[20px] bg-white px-[30px] pt-[34px] pb-7 text-[.92rem] leading-[1.45] text-so-ink shadow-[0_1px_2px_rgba(31,27,46,.06),0_16px_36px_-16px_rgba(46,16,101,.28)] max-[420px]:px-5 max-[420px]:pt-[26px] max-[420px]:pb-[22px] [--so-accent:#6d28d9] [--so-accent-dark:#5b21b6] [--so-ring:rgba(109,40,217,.22)] [--so-tile:#ece9f5]">
  <div class="mb-[18px] flex items-center justify-center gap-2.5 font-bold"><span class="grid size-[34px] place-items-center rounded-[10px] bg-(--so-accent) text-white"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l7 7-7 11-7-11z"/><path d="M12 3v18"/></svg></span>Kitepost</div>
  <h2 class="text-center text-[1.45rem] leading-[1.2] font-[750] tracking-[-.02em]" id="kp-title">Start your newsletter</h2>
  <p class="mt-1.5 mb-[22px] text-center text-so-muted">Publish to email and the web. Free up to 1,000 subscribers.</p>
  <div class="grid gap-2.5">
    <a class="relative flex min-h-[46px] items-center justify-center gap-2.5 rounded-[10px] border border-so-line bg-white px-3.5 py-2.5 font-semibold text-so-ink transition-[background-color,border-color,color] duration-150 hover:border-so-ink hover:bg-[#faf9fd] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--so-accent) motion-reduce:transition-none" href="#"><span class="grid size-6 place-items-center rounded-md bg-(--so-tile) text-[.74rem] font-extrabold text-so-ink absolute top-1/2 left-3 -translate-y-1/2" aria-hidden="true">G</span>Continue with Google</a>
    <a class="relative flex min-h-[46px] items-center justify-center gap-2.5 rounded-[10px] border border-so-line bg-white px-3.5 py-2.5 font-semibold text-so-ink transition-[background-color,border-color,color] duration-150 hover:border-so-ink hover:bg-[#faf9fd] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--so-accent) motion-reduce:transition-none" href="#"><span class="grid size-6 place-items-center rounded-md bg-(--so-tile) text-[.74rem] font-extrabold text-so-ink absolute top-1/2 left-3 -translate-y-1/2" aria-hidden="true">A</span>Continue with Apple</a>
    <a class="relative flex min-h-[46px] items-center justify-center gap-2.5 rounded-[10px] border border-so-line bg-white px-3.5 py-2.5 font-semibold text-so-ink transition-[background-color,border-color,color] duration-150 hover:border-so-ink hover:bg-[#faf9fd] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--so-accent) motion-reduce:transition-none" href="#"><span class="grid size-6 place-items-center rounded-md bg-(--so-tile) text-[.74rem] font-extrabold text-so-ink absolute top-1/2 left-3 -translate-y-1/2" aria-hidden="true">M</span>Continue with Microsoft</a>
  </div>
  <p class="my-[22px] flex items-center gap-3 text-[.8rem] text-so-muted before:h-px before:flex-1 before:bg-[#d7d4e2] before:content-[''] after:h-px after:flex-1 after:bg-[#d7d4e2] after:content-['']">or sign up with email</p>
  <form action="#" method="post" aria-labelledby="kp-title">
    <div class="mb-4">
      <label class="mb-1.5 block text-[.84rem] font-semibold" for="kp-name">Name <span class="font-bold text-(--so-accent)" aria-hidden="true">*</span></label>
      <input class="block w-full rounded-[10px] border border-so-line bg-white px-[13px] py-[11px] transition-[border-color,box-shadow] duration-150 focus:border-(--so-accent) focus:shadow-[0_0_0_3px_var(--so-ring)] focus:outline-none user-invalid:border-so-error motion-reduce:transition-none" id="kp-name" name="name" type="text" autocomplete="name" required>
    </div>
    <div class="mb-4">
      <label class="mb-1.5 block text-[.84rem] font-semibold" for="kp-email">Email <span class="font-bold text-(--so-accent)" aria-hidden="true">*</span></label>
      <input class="block w-full rounded-[10px] border border-so-line bg-white px-[13px] py-[11px] transition-[border-color,box-shadow] duration-150 focus:border-(--so-accent) focus:shadow-[0_0_0_3px_var(--so-ring)] focus:outline-none user-invalid:border-so-error motion-reduce:transition-none" id="kp-email" name="email" type="email" autocomplete="email" required>
    </div>
    <div class="mb-4">
      <label class="mb-1.5 block text-[.84rem] font-semibold" for="kp-pw">Password <span class="font-bold text-(--so-accent)" aria-hidden="true">*</span></label>
      <input class="block w-full rounded-[10px] border border-so-line bg-white px-[13px] py-[11px] transition-[border-color,box-shadow] duration-150 focus:border-(--so-accent) focus:shadow-[0_0_0_3px_var(--so-ring)] focus:outline-none user-invalid:border-so-error motion-reduce:transition-none" id="kp-pw" name="password" type="password" autocomplete="new-password" minlength="8" required aria-describedby="kp-pw-hint">
      <p class="mt-1.5 text-[.8rem] text-so-muted" id="kp-pw-hint">At least 8 characters. Fields marked * are required.</p>
    </div>
    <button class="mt-1 block w-full cursor-pointer rounded-[10px] bg-(--so-accent) px-4 py-3 font-semibold text-white transition-[background-color,border-color,color] duration-150 hover:bg-(--so-accent-dark) focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-(--so-accent) motion-reduce:transition-none" type="submit">Create account</button>
  </form>
  <p class="mt-3.5 text-center text-[.86rem] text-so-muted">Already on Kitepost? <a class="text-(--so-accent) underline underline-offset-2 hover:text-(--so-accent-dark) focus-visible:rounded-[3px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--so-accent)" href="#">Log in</a></p>
</div>
</div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#5f5a70] uppercase">Email first, icon row</span>
<div class="rounded-[20px] bg-white px-[30px] pt-[34px] pb-7 text-[.92rem] leading-[1.45] text-so-ink shadow-[0_1px_2px_rgba(31,27,46,.06),0_16px_36px_-16px_rgba(46,16,101,.28)] max-[420px]:px-5 max-[420px]:pt-[26px] max-[420px]:pb-[22px] [--so-accent:#15803d] [--so-accent-dark:#166534] [--so-ring:rgba(21,128,61,.22)] [--so-tile:#e7f3eb]">
  <div class="mb-[18px] flex items-center justify-center gap-2.5 font-bold"><span class="grid size-[34px] place-items-center rounded-[10px] bg-(--so-accent) text-white"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 21V11"/><path d="M12 11C12 7 9 4 4 4c0 5 3 7 8 7zM12 13c0-3 2.5-6 8-6 0 4.5-3 6-8 6z"/></svg></span>Sprigly</div>
  <h2 class="text-center text-[1.45rem] leading-[1.2] font-[750] tracking-[-.02em]" id="sg-title">Never forget to water again</h2>
  <p class="mt-1.5 mb-[22px] text-center text-so-muted">Care reminders for every plant in your home.</p>
  <form action="#" method="post" aria-labelledby="sg-title">
    <div class="mb-4">
      <label class="mb-1.5 block text-[.84rem] font-semibold" for="sg-email">Email address <span class="font-bold text-(--so-accent)" aria-hidden="true">*</span></label>
      <input class="block w-full rounded-[10px] border border-so-line bg-white px-[13px] py-[11px] transition-[border-color,box-shadow] duration-150 focus:border-(--so-accent) focus:shadow-[0_0_0_3px_var(--so-ring)] focus:outline-none user-invalid:border-so-error motion-reduce:transition-none" id="sg-email" name="email" type="email" autocomplete="email" required aria-describedby="sg-email-hint">
      <p class="mt-1.5 text-[.8rem] text-so-muted" id="sg-email-hint">Required. We'll email you a link to finish signing up.</p>
    </div>
    <button class="mt-1 block w-full cursor-pointer rounded-[10px] bg-(--so-accent) px-4 py-3 font-semibold text-white transition-[background-color,border-color,color] duration-150 hover:bg-(--so-accent-dark) focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-(--so-accent) motion-reduce:transition-none" type="submit">Continue with email</button>
  </form>
  <p class="my-[22px] flex items-center gap-3 text-[.8rem] text-so-muted before:h-px before:flex-1 before:bg-[#d7d4e2] before:content-[''] after:h-px after:flex-1 after:bg-[#d7d4e2] after:content-['']">or sign up with</p>
  <div class="grid grid-cols-3 gap-2.5">
    <a class="flex flex-col items-center gap-1.5 rounded-xl border border-so-line bg-white px-1.5 pt-3 pb-2.5 text-[.78rem] font-semibold text-so-ink transition-[background-color,border-color,color] duration-150 hover:border-so-ink hover:bg-[#faf9fd] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--so-accent) motion-reduce:transition-none" href="#" aria-label="Sign up with Google"><span class="grid size-[30px] place-items-center rounded-lg bg-(--so-tile) text-[.86rem] font-extrabold text-so-ink" aria-hidden="true">G</span>Google</a>
    <a class="flex flex-col items-center gap-1.5 rounded-xl border border-so-line bg-white px-1.5 pt-3 pb-2.5 text-[.78rem] font-semibold text-so-ink transition-[background-color,border-color,color] duration-150 hover:border-so-ink hover:bg-[#faf9fd] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--so-accent) motion-reduce:transition-none" href="#" aria-label="Sign up with Apple"><span class="grid size-[30px] place-items-center rounded-lg bg-(--so-tile) text-[.86rem] font-extrabold text-so-ink" aria-hidden="true">A</span>Apple</a>
    <a class="flex flex-col items-center gap-1.5 rounded-xl border border-so-line bg-white px-1.5 pt-3 pb-2.5 text-[.78rem] font-semibold text-so-ink transition-[background-color,border-color,color] duration-150 hover:border-so-ink hover:bg-[#faf9fd] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--so-accent) motion-reduce:transition-none" href="#" aria-label="Sign up with Facebook"><span class="grid size-[30px] place-items-center rounded-lg bg-(--so-tile) text-[.86rem] font-extrabold text-so-ink" aria-hidden="true">F</span>Facebook</a>
  </div>
  <p class="mt-4 text-center text-[.78rem] text-so-muted">By continuing you agree to Sprigly's <a class="text-(--so-accent) underline underline-offset-2 hover:text-(--so-accent-dark) focus-visible:rounded-[3px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--so-accent)" href="#">Terms</a> and <a class="text-(--so-accent) underline underline-offset-2 hover:text-(--so-accent-dark) focus-visible:rounded-[3px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--so-accent)" href="#">Privacy Policy</a>.</p>
</div>
</div>
</div>
CSS
@theme {
  --color-so-ink: #1f1b2e;
  --color-so-muted: #57536a;
  --color-so-line: #85819a;
  --color-so-error: #b91c1c;
}

About this set

Two sign-up cards that offer third-party accounts alongside an email form. Providers first is a newsletter platform sign-up with three full-width Continue with buttons for Google, Apple and Microsoft, an or sign up with email divider and a name, email and password form underneath. Email first, icon row is a plant care app that leads with a single email field and a Continue with email button, then offers three square provider buttons with the provider name under a letter tile. Use providers first when most of your users already have one of those accounts, and email first when you want a passwordless email link to be the main route. The provider buttons are links, because each one would start that provider’s sign-in redirect. They show a neutral letter tile rather than a brand logo, so replace them with each provider’s official button artwork and follow its brand rules when you connect the real sign-in. The or divider is a paragraph whose lines are drawn with ::before and ::after. There is no JavaScript; the browser validates the email form, and :user-invalid marks edited fields that need attention.

What’s included

  • Full-width provider buttons and a compact three-up icon row
  • Neutral letter tiles instead of third-party logos
  • Divider drawn with ::before and ::after on a text line
  • Email form with name, email and new-password autocomplete
  • No JavaScript

Accessibility

Provider buttons in the icon row carry an aria-label such as Sign up with Google that contains the visible text, and the letter tiles are aria-hidden. Every input has a visible label and autocomplete value, required fields are explained in words, and every link and button shows a visible focus ring. Transitions switch off under prefers-reduced-motion.

Customise it

Set --so-accent, --so-accent-dark, --so-ring and --so-tile on .so (.so--green is the second palette). Swap the .so-tile spans for provider artwork when you go live. In Bootstrap the provider buttons are .btn elements restyled through --bs-btn-* variables; in Tailwind edit the [--so-accent:…] properties on each card.