Footer with Four Link Columns and Newsletter Signup

A full site footer on a light grey background. The left block has the logo, a short pitch for a monthly email and a signup form that swaps to a confirmation message when submitted. To the right are four columns of links under clear headings. A bottom bar carries the copyright line, legal links and a small status badge. On phones the signup comes first and the columns fall into a two by two grid.

Code

import { useState } from "react";

const columns = [
  { title: "Product", links: ["Online booking", "Reminders", "Patient records", "Payments", "Integrations"] },
  { title: "Who it is for", links: ["Physiotherapy", "Dental practices", "Counselling", "Vet clinics"] },
  { title: "Resources", links: ["Help centre", "Setup guides", "Clinic stories", "Changelog"] },
  { title: "Company", links: ["About us", "Careers", "Press kit", "Contact"] },
];

const legal = ["Privacy", "Terms", "Cookies"];

export default function FooterWithFourLinkColumnsAndNewsletter() {
  const [sent, setSent] = useState(false);
  const focus = "focus:outline-none focus-visible:ring-2 focus-visible:ring-sky-700 focus-visible:ring-offset-2 focus-visible:ring-offset-slate-50";

  return (
    <footer className="border-t border-slate-200 bg-slate-50 px-6 pt-14 text-slate-900 sm:pt-20">
      <div className="mx-auto max-w-6xl">
        <div className="grid gap-12 lg:grid-cols-12 lg:gap-8">
          <div className="lg:col-span-4">
            <a href="#" className={`flex w-fit items-center gap-2.5 rounded-lg ${focus}`}>
              <svg viewBox="0 0 28 28" aria-hidden="true" className="h-7 w-7">
                <circle cx="14" cy="14" r="14" className="fill-sky-700" />
                <path d="M14 7.5v13M7.5 14h13" stroke="white" strokeWidth="2.6" strokeLinecap="round" />
              </svg>
              <span className="text-lg font-semibold tracking-tight">Wrenfield</span>
            </a>
            <h2 className="mt-8 text-base font-semibold">Clinic notes, once a month</h2>
            <p className="mt-2 max-w-sm text-sm leading-relaxed text-slate-600">
              One short email on running a calmer front desk: fewer no-shows, faster check-in and what we shipped.
            </p>
            {sent ? (
              <p role="status" className="mt-5 flex max-w-sm items-center gap-2.5 rounded-xl border border-sky-200 bg-white px-4 py-3 text-sm font-medium text-slate-800">
                <svg viewBox="0 0 20 20" fill="none" aria-hidden="true" className="h-5 w-5 flex-none text-sky-700">
                  <path d="m4.5 10.5 3.5 3.5 7.5-8" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                You are on the list. The next issue goes out on the first Tuesday.
              </p>
            ) : (
              <form
                action="#"
                onSubmit={(e) => {
                  e.preventDefault();
                  setSent(true);
                }}
                className="mt-5 flex max-w-sm gap-2"
              >
                <label htmlFor="footer-newsletter-email" className="sr-only">Email address</label>
                <input
                  id="footer-newsletter-email"
                  type="email"
                  required
                  placeholder="[email protected]"
                  className="h-11 w-full min-w-0 rounded-xl border border-slate-300 bg-white px-3.5 text-sm placeholder:text-slate-500 focus:border-sky-700 focus:outline-none focus:ring-2 focus:ring-sky-700/20"
                />
                <button type="submit" className={`h-11 flex-none rounded-xl bg-sky-700 px-4 text-sm font-semibold text-white transition hover:bg-sky-800 ${focus}`}>
                  Subscribe
                </button>
              </form>
            )}
            <p className="mt-3 text-xs text-slate-600">No tracking pixels. Unsubscribe with one click.</p>
          </div>

          <nav aria-label="Footer" className="grid grid-cols-2 gap-x-6 gap-y-10 sm:grid-cols-4 lg:col-span-8 lg:pl-12">
            {columns.map((col) => (
              <div key={col.title}>
                <h3 className="text-sm font-semibold text-slate-900">{col.title}</h3>
                <ul className="mt-2">
                  {col.links.map((l) => (
                    <li key={l}>
                      <a href="#" className={`inline-flex min-h-[40px] items-center rounded text-sm text-slate-600 transition hover:text-sky-800 ${focus}`}>{l}</a>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </nav>
        </div>

        <div className="mt-14 flex flex-col gap-4 border-t border-slate-200 py-6 text-sm text-slate-600 sm:flex-row sm:items-center sm:justify-between">
          <p>&copy; 2026 Wrenfield Health Software Ltd.</p>
          <ul className="-ml-2 flex flex-wrap items-center gap-y-1">
            {legal.map((l) => (
              <li key={l}>
                <a href="#" className={`inline-flex min-h-[40px] items-center rounded px-2 hover:text-slate-900 ${focus}`}>{l}</a>
              </li>
            ))}
            <li>
              <a href="#" className={`ml-2 inline-flex min-h-[40px] items-center gap-2 rounded-full border border-slate-200 bg-white px-3 text-slate-700 hover:border-slate-300 ${focus}`}>
                <span aria-hidden="true" className="h-2 w-2 rounded-full bg-emerald-500" />
                All systems normal
              </a>
            </li>
          </ul>
        </div>
      </div>
    </footer>
  );
}

Install with one command: npx shadcn@latest add https://we.inc/r/footer-with-four-link-columns-and-newsletter.json

When to use it

How to customize it

Accessibility

Questions

What should go in a website footer?

The links people look for at the end of a page: product areas, help and contact, company pages and legal documents. A newsletter form and a status link are useful extras. Leave out anything already obvious in the header unless visitors would miss it.

How many columns should a footer have?

Three to five works for most sites. Four columns fit in one row from tablet width upward and split evenly into two rows of two on phones, which is why this layout uses them.

How do I connect the newsletter form to my email tool?

Give the input a `name`, then in the `onSubmit` handler read the value and post it to your own endpoint or your email provider's form address. Call `setSent(true)` only after the request succeeds, and show an error message if it fails.

How do I keep the footer at the bottom on short pages?

Make the page wrapper `flex min-h-screen flex-col` and give the main content `flex-1`. The footer then sits at the bottom of the window when the content is short and follows the content when it is long.

Does it work with Tailwind CSS v3 and v4?

Yes. It uses core utilities only, with no plugins and no custom theme values.

Related: Minimal One-Line Footer with Social Icons, Dark Footer with Large Call to Action, Store Navbar with Announcement Bar and Category Row, Split Hero with Email Capture.

More footers or all free UI components. Start for free to have a full site built around it.

More in Footers

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap