Get your free splitforms access key
Sign up at splitforms.com, verify your email, and copy your access key from the dashboard. No credit card required.
Contact form · Tailwind CSS
A polished, accessible, dark-mode-ready Tailwind contact form template. Drop into any project that has Tailwind configured — Next.js, React, Astro, Vue, Svelte, plain HTML. Includes focus rings, validation states, loading spinner, and a working backend.

No server, API route, or SDK. Your Tailwind CSS form posts straight to one endpoint.
Every submission is emailed to you and saved to a searchable dashboard — spam filtered before it reaches you.
It's your own Tailwind CSS markup and styles. Splitforms is only the backend, so nothing constrains how the form looks.
Copy-paste ready
Replace YOUR_ACCESS_KEY with the key from your dashboard — that's the whole integration. No SDK to install, no build step, just the html you already write.
<form
action="https://splitforms.com/api/submit"
method="POST"
class="max-w-md mx-auto space-y-4 p-6 bg-white rounded-2xl border border-gray-200"
>
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<div>
<label class="block text-sm font-semibold text-gray-700 mb-1">Name</label>
<input name="name" type="text" required
class="w-full rounded-lg border border-gray-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-orange-500" />
</div>
<div>
<label class="block text-sm font-semibold text-gray-700 mb-1">Email</label>
<input name="email" type="email" required
class="w-full rounded-lg border border-gray-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-orange-500" />
</div>
<div>
<label class="block text-sm font-semibold text-gray-700 mb-1">Message</label>
<textarea name="message" rows="4" required
class="w-full rounded-lg border border-gray-300 px-3 py-2 focus:outline-none focus:ring-2 focus:ring-orange-500" />
</div>
<input type="checkbox" name="botcheck" class="hidden" tabindex="-1" />
<button type="submit"
class="w-full bg-orange-600 hover:bg-orange-700 text-white font-semibold py-2 rounded-lg transition">
Send message
</button>
</form>How to add it
To add a contact form to a Tailwind CSS website you need three things: a free splitforms access key, the html snippet above, and your key pasted into it. No backend, server, or SDK — the form posts to one URL and every submission lands in your inbox and dashboard.
Sign up at splitforms.com, verify your email, and copy your access key from the dashboard. No credit card required.
Copy the Tailwind CSS code example into your project and replace YOUR_ACCESS_KEY with the key from step 1.
Submissions arrive in the splitforms dashboard within seconds. Free includes inbox delivery; Pro adds Slack, Discord, Sheets, or any signed webhook URL.
Where submissions go
Every submission is emailed to you and saved to a searchable dashboard — spam filtered before it ever reaches you. Search, export to CSV, or forward it to a webhook or Slack on Pro.

No backend needed
Your Tailwind CSS form posts standard FormData to one URL. Splitforms validates the access key, runs the spam classifier, and forwards it to your email — so there's no server, API route, or database for you to build or maintain.

Best practices
The difference between a form that works in the demo and one that survives launch traffic — the production-tested defaults, in priority order.

How SplitForms works
Connect your form, collect every submission, and send data where it needs to go — without building backend infrastructure.

Point your form to your unique SplitForms endpoint. That's it.

We instantly capture and organize every submission in your inbox.

Send data to email, spreadsheets, CRMs, webhooks, and 7,000+ apps.

No credit card required. Set up in under 60 seconds.
Connect & automate
SplitForms works with the destinations you route to and the platforms you build on — from Slack and Sheets to WordPress, Shopify, and Next.js.

Trusted by indie teams and agencies shipping forms worldwide
Testimonials
40 quotes on record — from indie hacks to agency migrations.
“I replaced a Lambda + DynamoDB + SES contact form with six lines of HTML. It took eleven minutes, and the dashboard is better than what I was going to build.”
“We migrated 14 client sites off Formspree in a single weekend. The price is a third of what we paid, the API is more honest, and the spam filter actually works.”
“The webhook payload is signed, idempotent, and well-shaped. It reads like code from a competent team, not a CRUD app held together with duct tape.”
“I stopped reaching for Typeform on small marketing sites. splitforms covers 90% of the use case at none of the bloat.”
“I onboarded our whole agency in an afternoon. The MCP integration meant Cursor literally dropped the form straight into our client repos for us.”
“The free plan gave me 500 submissions before I paid a cent, and Pro is five dollars a month. I've spent more on coffee deciding which backend to use.”
“Spam went from forty junk entries a day to zero, with no reCAPTCHA puzzle ruining the form. The honeypot and time-trap just quietly do their job.”
“Point the form action at one endpoint and you're done. No SDK, no client library, no build step. This is how a form backend should feel.”
“Leads land in Slack the second someone submits, and a copy goes to Google Sheets for the sales team. I wired both up in under ten minutes.”
“I run a static Hugo site on a five-dollar VPS. splitforms gave it a real contact form without me standing up a single server.”
Questions
Copy the snippet above into any component or HTML file. Make sure Tailwind is already configured in your project (you'd see tailwind.config.js and the @tailwind directives in your CSS). Replace YOUR_ACCESS_KEY with your splitforms key.
Yes. The hero snippet uses utilities that exist in both versions. The dark-mode alternative uses dark: variants — ensure your config has the dark-mode strategy you want (media or class).
Add a hidden error <p> below the form and toggle visibility on submit. Tailwind utilities for error state: text-red-600 dark:text-red-400 text-sm mt-2. The fetch returns { success, message } — toggle the p's hidden class based on success.
Yes, but the plugin resets input styles. Either remove the snippet's per-input padding/border classes (the plugin will style them), or remove the plugin from your config and use the snippet's explicit utilities.
Set your thank-you page URL in Dashboard → Form settings → Redirect for a native 302 after success. For inline confirmation, leave that setting empty, wrap the form in a JS handler, and toggle a Tailwind-styled success <div>.
The hero snippet is light-mode only (so it works regardless of your dark-mode setup). The alternative-pattern snippet includes full dark: variants — use it if your project supports dark mode.
If you build the form HTML inside a JS template literal, Tailwind's JIT can't see your classes and purges them. Either move the markup into a .html / .tsx / .vue file, or add the classes to your safelist in tailwind.config.js.
Tailwind 4 (released 2026) moved theme tokens into CSS via @theme { … }. If you copy a Tailwind 3 snippet using focus:ring-orange-500, the orange-500 token has to be defined in your @theme block or it falls back to no ring color. Use a CSS variable: focus:ring-[var(--accent)] for portability.
If you're embedding the form inside a Shadow DOM, iframe, or a CMS that strips global CSS, Tailwind's Preflight (the global reset) doesn't apply. Inputs render with browser-default white backgrounds, ignoring bg-white if you set it in @apply but not as a utility on the element. Always use utilities directly on the input.
Tailwind defaults to media-query dark mode (prefers-color-scheme). If your form has dark:bg-gray-900 and you toggle dark mode via a class on <html>, you need darkMode: 'class' in tailwind.config.js (Tailwind 3) or @variant dark (.dark &) in your CSS (Tailwind 4).
The official forms plugin resets input styles aggressively. Combined with our pre-styled snippet, you may get double-padded inputs. Either remove @tailwindcss/forms from your config, or use class="form-input" and let the plugin style everything.
Adding peer-invalid:border-red-500 to inputs styled by a sibling peer class seems clean — but the :invalid pseudo-class is true the moment a required empty input renders, so the whole form lights up red before the user has typed anything. Combine with :user-invalid (modern browsers) or guard with peer-[:not(:placeholder-shown)]:peer-invalid:border-red-500 so red only appears after the user has actually interacted. Tailwind 3.4+ adds the user-invalid variant directly; earlier versions need an arbitrary variant.
Tailwind is a styling layer — it has no opinion on form submission, networking, or backend. The 'native' approach means writing utility classes for visual treatment and bringing your own delivery mechanism: a Next.js route handler, a Vite + React + fetch combo, an HTMX endpoint, etc. Tailwind UI ($299 one-time) sells styled form templates but doesn't include a backend either. Tailwind v4's @theme directive changes how tokens are defined, not what forms do. The shape of the problem stays: utility classes for look-and-feel, splitforms for delivery. Drop the snippet on this page into any framework with Tailwind configured and you have a styled, working form in 60 seconds.
Tailwind is purely a build-time concern — utilities are compiled into your CSS bundle, then deployed as static assets. JIT mode (default in v3+) and the v4 engine both purge unused classes; if you build form HTML inside a JS template literal at runtime, Tailwind can't see those classes and purges them — add to safelist or move markup into source files. Works on every host. For dark mode toggled via class, set darkMode: 'class' in v3 config or use @variant dark (.dark &) in v4 CSS. The @tailwindcss/forms plugin resets input styles aggressively — pick one (plugin OR explicit utilities), not both.
Simple pricing
Choose a plan that fits your workflow — from a free form endpoint to full automations, exports, and higher submission limits.
Free forever
For side projects and indie devs.
For agencies and growing products.
Pay $59. 3 years sorted.
No credit card required on Free • Cancel anytime