Log in

Modern contact form

The card-on-a-gradient look, written out in full so you can see exactly which properties do the work. It is a shadow, a border radius, and a focus ring — every visual effect here is four or five lines of CSS, not a component library.

Live preview: this is the HTML and CSS below, rendered as-is.

Replace YOUR_FORM_ID with a form of your own and this sends to your inbox.

Create your form
contact.html
<form class="card-form" action="https://submit.formpost.ai/YOUR_FORM_ID" method="POST">
  <header>
    <h2>Get in touch</h2>
    <p>We usually reply within one working day.</p>
  </header>

  <div class="field">
    <label for="name">Name</label>
    <input id="name" type="text" name="name" required>
  </div>

  <div class="field">
    <label for="email">Email</label>
    <input id="email" type="email" name="email" required>
  </div>

  <div class="field">
    <label for="message">How can we help?</label>
    <textarea id="message" name="message" rows="4" required></textarea>
  </div>

  <button type="submit">Send message</button>
  <p class="fine-print">We will only use your address to reply.</p>
</form>
contact.css
body {
  margin: 0;
  padding: 48px 16px;
  background: linear-gradient(160deg, #eef2ff 0%, #fdf2f8 100%);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.card-form {
  box-sizing: border-box;
  width: 100%;
  max-width: 440px;
  margin: 0 auto;
  padding: 32px;
  background: #fff;
  border: 1px solid rgba(15, 23, 42, 0.06);
  border-radius: 20px;
  box-shadow: 0 24px 48px -24px rgba(15, 23, 42, 0.25);
}

.card-form header {
  margin-bottom: 24px;
}

.card-form h2 {
  margin: 0;
  font-size: 24px;
  letter-spacing: -0.02em;
  color: #0f172a;
}

.card-form header p {
  margin: 6px 0 0;
  font-size: 14px;
  color: #64748b;
}

.field {
  margin-bottom: 18px;
}

.field label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 600;
  color: #334155;
}

.field input,
.field textarea {
  box-sizing: border-box;
  width: 100%;
  padding: 12px 14px;
  font: inherit;
  color: #0f172a;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}

.field input:focus,
.field textarea:focus {
  background: #fff;
  border-color: #6366f1;
  box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.15);
  outline: none;
}

.field textarea {
  resize: vertical;
}

.card-form button {
  width: 100%;
  padding: 13px 16px;
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: linear-gradient(135deg, #6366f1, #a855f7);
  border: 0;
  border-radius: 12px;
  cursor: pointer;
  transition: filter 0.15s, transform 0.05s;
}

.card-form button:hover {
  filter: brightness(1.08);
}

.card-form button:active {
  transform: translateY(1px);
}

.fine-print {
  margin: 14px 0 0;
  font-size: 12px;
  text-align: center;
  color: #94a3b8;
}

What actually makes it look modern

Three things, and none of them are the gradient. The shadow uses a negative spread and a large blur so it reads as ambient light rather than a drop shadow. The inputs sit on a slightly darker fill than the card, which separates them without a heavy border. And the focus state grows a soft ring instead of the browser default.

the three rules that matter
box-shadow: 0 24px 48px -24px rgba(15, 23, 42, 0.25);

background: #f8fafc;
border: 1px solid #e2e8f0;

box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.15);

The focus ring is not decoration

Anyone navigating by keyboard needs to see which field they are in. The rule here sets outline: none and immediately replaces it with a box-shadow ring plus a colour change — that is fine. Setting outline: none and stopping there is the single most common accessibility failure in styled forms.

Transitions worth having

The inputs transition border-colour, shadow and background together over 150ms. That is short enough to feel instant and long enough to be noticed. The button transitions brightness on hover and drops one pixel on :active, which is the cheapest way to make a button feel like a physical control.

Deliberately absent: any transition on layout properties. Animating width, height or padding on a form makes it feel unstable while somebody is trying to type into it.

Wiring it up

None of the styling changes how the form sends. Set the action to your endpoint and the modern contact form posts exactly like a plain one:

<form class="card-form" action="https://submit.formpost.ai/YOUR_FORM_ID" method="POST">
The gradient lives on body, not on the form. Drop that rule and the card sits happily on whatever background your page already has.

Questions about this contact form

Does this need Tailwind or a CSS framework?
No. It is one stylesheet of ordinary CSS with no dependencies, no build step and no classes borrowed from anywhere. If you do use Tailwind, there is a version of this form written entirely in utility classes.
Will the gradient button work in older browsers?
linear-gradient has been supported everywhere for over a decade. The one modern property here is box-shadow with a negative spread, which is equally old. Nothing degrades badly — worst case a browser shows a flat colour.
How do I match it to my brand?
Change the two colours in the button gradient and the rgba value in the focus ring. Those three values are the entire palette; everything else is neutral slate and will sit under any accent colour.
Can I make this contact form submit without reloading the page?
Yes. Keep the markup exactly as it is and add a small submit handler that posts the FormData with fetch and an Accept: application/json header. The AJAX contact form example has the complete code.

Related examples

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.