How to build a basic Tailwind footer
Everything happens through utility classes on a footer element, so spacing, color and layout live in the markup and no separate stylesheet is involved.
The base is a footer tag, a centered container, a nav with a handful of links, and a copyright line.
Every class below exists in both Tailwind v3 and v4. Tailwind Labs shipped v4.0 in January 2025, and the v4.3 line is current as of October 2026 (the latest release, v4.3.3, came out in July).
Anyone who has built footers in plain CSS will recognize the structure. Only the styling moves from a stylesheet into class attributes.
- Open a sandbox. Tailwind Play runs in the browser with no install, and the Tailwind CSS IntelliSense extension for VS Code adds class autocomplete and linting in a local project.
- Add the footer tag as a direct child of body, after main, with a background and a text color.
- Wrap the content in a container:
mx-auto max-w-7xl px-6 py-12. - Put the links in a nav element and space them with
flex flex-wrap gap-x-8 gap-y-3. - Add the copyright line under a
border-t divider. - Resize the preview to 320px and to a desktop width, then fix whatever wraps badly.
<footer class="bg-gray-900 text-gray-300">
<div class="mx-auto max-w-7xl px-6 py-12">
<nav aria-label="Footer" class="flex flex-wrap gap-x-8 gap-y-3 text-sm">
<a href="/about" class="hover:text-white">About</a>
<a href="/pricing" class="hover:text-white">Pricing</a>
<a href="/contact" class="hover:text-white">Contact</a>
<a href="/privacy" class="hover:text-white">Privacy</a>
</nav>
<p class="mt-10 border-t border-gray-800 pt-8 text-sm text-gray-400">
© 2026 Example Inc. All rights reserved.
</p>
</div>
</footer>
That shell works on its own. Columns, icons and a newsletter form get added on top of it.
How to lay out and stack footer columns with grid and flex
Grid handles the link columns. The bottom bar is a flex job. Once a footer has 3 or more labelled link columns (Product, Company, Legal), grid is the right tool, while a copyright row with 2 items doesn’t need it.
Grid for link columns
Sitemap footers usually start from grid grid-cols-2 gap-8 md:grid-cols-4, which gives equal columns that collapse on small screens.
The grid class makes the wrapper a grid container, and grid-cols-2 gives two equal columns on mobile. From the md breakpoint up, md:grid-cols-4 takes over with four columns. gap-8 leaves 2rem between columns and rows.
The Tailwind documentation shows grid-cols-4 generating grid-template-columns: repeat(4, minmax(0, 1fr)). Those tracks stay equal and can shrink below their content width.
That shrinking is why a long email address overflows its column instead of widening it. Add wrap-break-word to any link text that holds long strings (the older break-words name still compiles in v4).
Flex for the bottom bar
Two or three items in one row is a flex job.
Stack them on mobile and spread them from md up with flex flex-col gap-4 md:flex-row md:items-center md:justify-between.
Copyright text goes on the left and social icons at the far end, with the privacy and terms links somewhere between.
Flex wins here because the items have different widths, and nobody wants them forced into equal tracks. Once the row grows past 4 items, move it into the grid above.
Breakpoint stacking
The Tailwind documentation lists 5 default breakpoints: sm, md, lg, xl and 2xl. In v4 they are defined in rem, with lg at 64rem, xl at 80rem and 2xl at 96rem.
Tailwind takes a mobile-first approach. Unprefixed classes set the small-screen layout, and a prefix such as md: applies from that width and stays applied above it.
Each prefix compiles to one of the media queries in the generated stylesheet, so no JavaScript is involved.
Below md the footer shows two link columns with the copyright stacked under them. From md up it switches to four columns, and the bottom bar spreads across the full width.
Two columns is the better mobile default. One column holding every sitemap link turns the footer into a long scroll.
Which footer pattern fits which kind of site?
Match the pattern to how many destinations the site links to, not to whichever design looks best in a gallery. A portfolio needs a one-row bar, a SaaS product needs a sitemap.
Tailwind Plus listed 7 footer components built by the Tailwind team before it closed to new customers in September 2026. Material Tailwind’s PRO blocks add centered, country-selector and complex dark variants with a newsletter field, and the designs from both catalogs end up in the table below.
| Pattern | Blocks included | Best for |
|---|
| Simple one-row | Copyright, a few links | Portfolios, small business sites |
| Centered | Logo, links, social icons, copyright | Personal brands, blogs |
| Multi-column sitemap | Logo, 4 to 5 link columns, legal row | SaaS, documentation, content sites |
| Dark with newsletter | Email field, button, link columns | Product launches, marketing sites |
| App footer | Store badges, country selector, legal links | Mobile apps, international sites |
Those 5 patterns cover nearly everything in either catalog.
A dark footer with an email field and a button carries a single call to action. It suits pages built to collect sign-ups and wastes space on a five-page brochure site.
The blocks themselves are navigation links, legal links (privacy policy, terms of service), contact details, social icons, a newsletter form and the copyright line. Pick only the ones the site needs. A small site with no mailing list should skip the newsletter form instead of filling the space.
Social icons need a brand set. Heroicons, the free SVG set Tailwind Labs designed for its own components, covers interface icons like navigation and actions, so brand logos come from somewhere else.
Font Awesome Free icons are CC BY 4.0, so attribution applies, though the downloaded files carry comments that satisfy it (Font Awesome Free License). Simple Icons ships SVG brand icons under CC0 and asks for no attribution at all.
Brand logos stay trademarks of their owners under either set, and Font Awesome’s license says to use each one only for the brand it shows. Give every icon link an aria-label that names the platform.
How do you keep a Tailwind footer at the bottom of the page?
Make the page wrapper a flex column that is at least as tall as the screen, then let main grow or push the footer down with mt-auto. The footer lands on the bottom edge of short pages and follows the content on long ones.
<body class="flex min-h-screen flex-col">
<header>...</header>
<main class="grow">...</main>
<footer class="mt-auto">...</footer>
</body>
Either grow on main or mt-auto on the footer is enough, and using both does no harm. Older tutorials write flex-grow for the same effect, but Tailwind v4 removed that class in favor of grow.
Auto margins only push when the parent is a flex or grid container with spare height. Put mt-auto on a footer inside a plain block wrapper and nothing happens.
The class min-h-screen sets min-height: 100vh, the full height of the viewport.
On phones, 100vh equals the largest possible viewport, so the footer can sit just below the visible edge while the address bar is showing. Tailwind’s min-h-dvh utility (min-height: 100dvh) is the fix, because dvh follows the browser interface as it expands and contracts.
The phrase sticky footer gets stretched over several different behaviors. A flex column with mt-auto pushes the footer down, so it sits at the bottom of short pages and scrolls away on long ones. sticky bottom-0 pins it on screen while the page scrolls, but only inside a parent tall enough to scroll. And fixed bottom-0 takes the footer out of the document flow, which means main needs bottom padding or the last lines vanish behind it.
Tutorials mix these up. Some posts sold as a sticky footer build a regular one, which stops staying on screen once the content is taller than the window.
For a site footer, pushed down is the right default. A pinned footer holding a full sitemap eats screen space at every scroll position, so keep pinning for app toolbars.
Dark mode in a Tailwind footer
Tailwind v4 applies dark: classes when the operating system prefers a dark color scheme, and one line of CSS switches that to a class you control. Add @custom-variant dark (&:where(.dark, .dark *)); after the Tailwind import (Tailwind documentation).
| Version | Toggle by class | Where it lives |
|---|
| Before v3.4.1 | darkMode: ‘class’ | tailwind.config.js |
| v3.4.1 and later | darkMode: ‘selector’ | tailwind.config.js |
| v4 | @custom-variant dark | Main CSS file |
Every class that carries color needs a dark value. The background becomes bg-gray-100 dark:bg-gray-900, and text goes from text-gray-600 to dark:text-gray-400. Link hover is hover:text-gray-900 dark:hover:text-white, and dividers use border-gray-200 dark:border-gray-800.
To follow the system until a visitor picks a theme, toggle the class from a small script that reads localStorage and window.matchMedia. Run it inline in the head so the page does not flash the wrong theme first.
Plenty of sites keep the footer dark in both themes. A fixed bg-gray-900 footer needs no dark: variants at all, and I’d go that way on most sites, since it removes a whole set of color pairs to test.
Making a Tailwind footer accessible
A footer becomes the page’s contentinfo landmark only when it belongs to body. Nested inside main, article, section, aside or nav, it falls back to a generic element with no landmark role (MDN Web Docs).
Screen reader users jump between landmarks, so a missing or duplicated contentinfo costs them a shortcut. MDN’s page on the contentinfo role says a page should have only one, and asks for an aria-label on each landmark when a document holds more than one. More on landmarks in the guide to ARIA.
In practice that means one top-level footer per page, kept outside main. Footers inside articles or sections shouldn’t get a role attribute, and every nav in the footer (Footer, Legal, Social) needs its own aria-label.
Sources split on one detail. MDN notes a known VoiceOver issue and suggests role="contentinfo" for older Safari, while validators such as Rocket Validator flag that same attribute on a footer as redundant.
Skip the role by default. Add it only when a test on an old Safari build shows the landmark missing.
WCAG 2.2 success criterion 1.4.3 sets the minimum at 4.5:1 for normal text and 3:1 for large text. A ratio of 4.499:1 does not round up to a pass (W3C).
Dark footers are where this slips, because the soft gray that looks calm is often the one that fails. Check the color contrast of every text class in the footer.
The ratios below are calculated from Tailwind v4’s default gray palette values with the WCAG relative luminance formula.
| Text class | On bg-gray-900 | Passes 4.5:1 |
|---|
| text-gray-300 | 12.06:1 | Yes |
| text-gray-400 | 6.82:1 | Yes |
| text-gray-500 | 3.67:1 | No |
Moving the background to bg-gray-950 lifts text-gray-500 to 4.16:1, still short. Keep that shade for dividers, not for links or the copyright line.
Free or paid: where to get ready-made Tailwind footers
Start free. HyperUI, Flowbite, daisyUI and Preline UI cover most footer patterns at no cost, and Tailwind Plus no longer sells to new customers.
| Source | License and cost | Delivery |
|---|
| Tailwind Plus | Paid, closed to new customers since September 2026 | Copy-paste examples in React, Vue and HTML |
| HyperUI | MIT, free | Copy-paste HTML, no install |
| Flowbite | MIT, free | Components plus React and Svelte packages |
| daisyUI | MIT, free | Plugin with footer class names |
| Preline UI | MIT and Fair Use License, free | npm package and Tailwind plugin |
Tailwind Labs announced on September 9, 2026 that it is joining Shopify and closing sign-ups for new customers, while existing customers keep their access to Tailwind Plus (Tailwind blog). Every Tailwind Plus page now redirects to a login screen.
For the quickest copy-paste, HyperUI wins because there is nothing to install. daisyUI has the shortest markup, since footer, footer-title and footer-center replace long utility strings (the v5 docs add footer-horizontal and footer-vertical). Flowbite reaches the most frameworks, with a documented footer component and one listed in its React and Svelte packages. Tailwind Plus only matters if you already own a license.
Preline UI is free for personal and commercial projects under its dual license, and Preline Pro is the paid tier above it.
Two older kits still turn up in searches. Meraki UI is MIT-licensed, built on flexbox and grid, with dark mode and RTL support, while Tailblocks ships 60+ copy-paste blocks under MIT with a 2020 copyright in its README.
Framework layouts
A footer belongs in the layer every page shares.
In Next.js that is the root layout, next to {children}. It is required, wraps every page, and does not re-render on navigation (Next.js documentation). Astro uses a layout component with a slot, and its documentation lists footers among the shared UI. React just needs a Footer component imported into App or the page layout. Vue works the same way with a single-file component imported into App.vue, where class attributes paste in unchanged.
Pasted HTML needs class changed to className in React and Next.js. An HTML to JSX converter does that along with self-closing tags.
Tailwind has to be set up in the project first, and the walkthrough on using Tailwind CSS in React covers it.
When a copied Tailwind footer breaks
Most broken pastes come down to a version mismatch, class names built from variables, dark: classes that ignore the toggle, or a landmark role the page already has.
Version mismatch
Creative Tim’s collection of free Tailwind footers filters its examples by Tailwind version 1, 2 and 3, with no v4 option.
The reverse problem exists too. Tailwind v4 is designed for Safari 16.4+, Chrome 111+ and Firefox 128+, and the upgrade guide tells projects with stricter cross-browser compatibility needs to stay on v3.4.
The border is a visible example. A bare border-t divider drew gray-200 in v3 and draws currentColor in v4 (Tailwind upgrade guide), so footers pasted from v3 kits need an explicit border color.
Class names that never generate
Tailwind reads source files as plain text, so it only generates classes that appear as complete strings (Tailwind documentation).
Something like bg-${color}-900 breaks, because bg-red-900 never exists anywhere in the source. A lookup object that holds full strings like bg-gray-900 and bg-white, mapped from the prop, works fine.
Footers pulled from a component package in node_modules are skipped by default, since Tailwind ignores files listed in .gitignore. Register the package path with @source.
Dark classes that ignore the toggle
When the footer stays light while the html element carries the dark class, go through these in order.
- Open the compiled CSS and look for
@media (prefers-color-scheme: dark) around the dark: rules. If they sit inside it, the custom variant is missing. - Confirm the variant line comes after the Tailwind import, as in the documentation example.
- Confirm the script puts the class on html, not on body or the footer.
Duplicate landmarks
Forcing role="contentinfo" on a footer inside main creates a second landmark the page does not expect. Axe-core’s landmark-contentinfo-is-top-level rule flags it, and a second contentinfo on the page also trips axe-core’s landmark-no-duplicate-contentinfo rule.
Move the footer out of main and delete the role attribute.
Tailwind Footer FAQ
Do I need JavaScript for a Tailwind footer?
No. Columns, hover states and breakpoints are all handled by classes in the markup.
Scripts only come in for a theme toggle or a self-updating year, and both are optional.
How do I update the copyright year automatically?
Render it from code instead of typing it. In plain HTML, a one-line script that sets textContent to new Date().getFullYear() does it.
In React, Next.js or Astro, put the same expression inside the footer component.
How do I add a newsletter form to a footer?
Put a form in one grid column with an email input and a submit button. Add a label as well, and hide it with sr-only if the design has no room, so the field keeps an accessible name.
Use flex-col on phones and sm:flex-row from the small breakpoint up.
How do I center everything in the footer?
Add text-center for text, and flex justify-center on the row that holds the links.
Keep mx-auto max-w-7xl on the inner wrapper so the content stays centered on wide screens too.
Can I use the Tailwind Play CDN for a production footer?
No. Tailwind’s documentation describes the Play CDN as built for development only, not for production use.
Compile the CSS with the CLI, the Vite plugin or PostCSS before the site goes live.
How do I add a back-to-top link?
Use an anchor with href="#top". Browsers treat that fragment as the start of the document, so no id is needed.
Add scroll-smooth to the html element if the jump should animate.
Building a Tailwind Footer in the Right Order
A Tailwind footer holds up best when the work runs from structure to style to behavior. Each step shrinks what the next one has to check.
- Footer element and landmark placement
- Responsive grid and bottom bar
- Text and background pairs, tested for contrast
- Dark variants, then the framework component
Color comes before dark mode because every dark variant adds a second set of color pairs to verify. A gray that fails in the light theme gets fixed once, not twice.
Starting from a ready-made block trades setup time for an audit. The copied markup carries its author’s Tailwind version, so border colors, the dark variant line and class names need a check before launch.
This order was verified against the Tailwind v4.3 documentation on October 29, 2026. A new major release that changes the CSS-first configuration would send the dark mode variant line to the top of that check.