A contact form in Tailwind that looks finished
Tailwind forms tend to look half-done because the fiddly states get skipped: visible focus, disabled styling, error borders. This one has them, in plain utilities with no plugin dependency, so it drops into any Tailwind project without touching the config. Swap the endpoint placeholder and it delivers.
Copy-paste HTML
<form action="https://send.webforms.to/wft_your_key" method="POST" class="mx-auto max-w-md space-y-5">
<div>
<label for="tw-name" class="mb-1.5 block text-sm font-medium text-gray-700">Name</label>
<input id="tw-name" name="name" type="text" required
class="w-full rounded-lg border border-gray-300 px-3.5 py-2.5 text-gray-900 shadow-sm
focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/30
invalid:[&:not(:placeholder-shown)]:border-red-400" placeholder=" ">
</div>
<div>
<label for="tw-email" class="mb-1.5 block text-sm font-medium text-gray-700">Email</label>
<input id="tw-email" name="email" type="email" required
class="w-full rounded-lg border border-gray-300 px-3.5 py-2.5 text-gray-900 shadow-sm
focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/30
invalid:[&:not(:placeholder-shown)]:border-red-400" placeholder=" ">
</div>
<div>
<label for="tw-message" class="mb-1.5 block text-sm font-medium text-gray-700">Message</label>
<textarea id="tw-message" name="message" rows="4" required
class="w-full rounded-lg border border-gray-300 px-3.5 py-2.5 text-gray-900 shadow-sm
focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/30"></textarea>
</div>
<button type="submit"
class="w-full rounded-lg bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white shadow-sm
transition-colors hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600
disabled:cursor-not-allowed disabled:opacity-60">
Send message
</button>
</form>Replace https://send.webforms.to/wft_your_key with your own endpoint from the WebForms dashboard.
Why these fields
- The invalid:[&:not(:placeholder-shown)] variant shows the red border only after the visitor has typed something invalid - not on page load, when every empty required field is technically invalid. The placeholder=' ' makes :placeholder-shown usable for this.
- focus:ring-2 with a translucent ring color gives an obvious, accessible focus state that doesn't look like a browser default.
- Disabled button styling is included even though nothing disables it in plain HTML - the moment you add an AJAX handler, the state exists and already looks right.
- Gray-scale text colors assume a light background; for dark UIs, swap the grays and keep the structure.
Where to send it
Get your endpoint
Free for 300 submissions a month. No card required.
Start freeTailwind CSS contact form FAQ
No. The plugin normalizes native control styling globally; this form styles everything it uses explicitly, so it behaves the same with or without it.
The action points at a placeholder endpoint. Create a free form, paste your real endpoint, and choose where it delivers - email, Slack, a webhook, or several at once.