Tailwind CSS contact form
Every style is a utility class on the element, so there is no stylesheet to add and nothing to configure. Paste it into any project that already has Tailwind and it looks like this immediately.
Replace YOUR_FORM_ID with a form of your own and this sends to your inbox.
<form
action="https://submit.formpost.ai/YOUR_FORM_ID"
method="POST"
class="mx-auto flex max-w-md flex-col gap-4 rounded-2xl border border-slate-200 bg-white p-8 shadow-sm"
>
<h2 class="text-xl font-semibold text-slate-900">Contact us</h2>
<div class="flex flex-col gap-1.5">
<label for="name" class="text-sm font-medium text-slate-700">Name</label>
<input
id="name"
name="name"
required
class="rounded-lg border border-slate-300 px-3 py-2 text-slate-900 placeholder:text-slate-400 focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/30"
/>
</div>
<div class="flex flex-col gap-1.5">
<label for="email" class="text-sm font-medium text-slate-700">Email</label>
<input
id="email"
type="email"
name="email"
required
class="rounded-lg border border-slate-300 px-3 py-2 text-slate-900 placeholder:text-slate-400 focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/30"
/>
</div>
<div class="flex flex-col gap-1.5">
<label for="message" class="text-sm font-medium text-slate-700">Message</label>
<textarea
id="message"
name="message"
rows="4"
required
class="resize-y rounded-lg border border-slate-300 px-3 py-2 text-slate-900 placeholder:text-slate-400 focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/30"
></textarea>
</div>
<button
type="submit"
class="rounded-lg bg-indigo-600 px-4 py-2.5 font-medium text-white transition hover:bg-indigo-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
Send message
</button>
</form>Utilities, not @apply
It is tempting to collapse the repeated input classes into a .input rule with @apply. Resist it for a form this size: you have reinvented a component stylesheet, given up the ability to tweak one field in place, and the repetition you were avoiding was four lines. @apply starts paying off at the point where the same combination appears across several files.
The focus ring is three utilities
focus:border-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/30focus:outline-none on its own would be an accessibility bug — it is only safe here because the ring utilities on the same element put the indicator back. On the button, prefer focus-visible: so a mouse click does not leave a ring behind.
Spacing with gap, not margins
The form is a flex column with gap-4, and each field is a flex column with gap-1.5. Nothing carries a margin, which means no collapsing margins, no last-child override, and adding or reordering a field never disturbs the spacing.
Version notes
- This markup works on Tailwind v3 and v4 without changes. The utilities used have been stable across both.
- Opacity shorthand (ring-indigo-500/30) needs v3 or newer. On older versions use ring-opacity-30.
- You do not need the forms plugin. It normalises input appearance across browsers, which is useful — but every property it would set is set explicitly here.
- If your build strips unused classes, make sure this file is inside your content globs, or the form will render unstyled.
Questions about this contact form
- Do I need the Tailwind forms plugin?
- No. The plugin normalises browser defaults, which is handy, but this markup sets every relevant property itself — border, padding, radius, focus ring. It renders identically with or without it.
- Should I use @apply to shorten the repeated classes?
- Not for one form. You would trade the ability to adjust a single field for a component stylesheet you now have to maintain. @apply pays off when the same combination is repeated across files.
- Why is my form unstyled after building?
- The file is outside your content globs, so the classes were purged. Add its path to the content array in your Tailwind config.
- Does this work with Tailwind v4?
- Yes, unchanged. Every utility used here behaves the same on v3 and v4, including the slash opacity syntax on the ring colour.
Related examples
Modern contact form
A soft card, a gradient button and a proper focus ring. Pure CSS, no library.
Bootstrap contact form
Bootstrap 5 classes as they come — form-control, form-label, btn-primary.
CSS contact form
Every state styled: hover, focus-visible, invalid, disabled, placeholder.
Or go back to all 21 contact form examples.
Give this form an endpoint
Formpost takes the submission, emails it to you and keeps a searchable copy. Free for 250 messages a month, with unlimited forms and no card.