On this page
A contact form is often the first form anyone adds to a website — and also the one most often done badly. Messages go missing, spam floods in, or the form only works if you set up a mail server.
This guide builds a contact form that does the job properly: clear fields, sensible validation, spam protection, and reliable delivery to your inbox. It works on any website, including static hosts like GitHub Pages and Netlify.
What a good contact form needs
- Only essential fields. Name, email and message. Every extra field lowers the number of people who finish.
- A valid reply address. Use
type="email"so you can actually write back. - Spam protection that doesn't punish real people.
- Clear feedback after sending, so people know it worked.
- Reliable delivery — the message must reach you.
The HTML
<form class="contact" action="https://api.formclick.io/submit" method="POST">
<!-- Your Formclick access key -->
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">
<input type="hidden" name="subject" value="New contact form message">
<input type="hidden" name="from_name" value="Website Contact Form">
<!-- Honeypot spam trap -->
<input type="checkbox" name="botcheck" class="hp" tabindex="-1" autocomplete="off">
<h2>Get in touch</h2>
<p>We usually reply within one business day.</p>
<div class="row">
<div class="field">
<label for="name">Name</label>
<input id="name" name="name" type="text" autocomplete="name" required>
</div>
<div class="field">
<label for="email">Email</label>
<input id="email" name="email" type="email" autocomplete="email" required>
</div>
</div>
<div class="field">
<label for="message">How can we help?</label>
<textarea id="message" name="message" rows="6" required minlength="10"></textarea>
</div>
<button type="submit">Send message</button>
</form>
<script src="https://cdn.formclick.io/formclick.min.js"></script>
What each hidden field does:
access_keytells Formclick which form (and inbox) the message belongs to.subjectbecomes the subject line of your notification email.from_nameis the sender name you'll see in your inbox.botcheckis a hidden honeypot. People never see or tick it; simple bots fill in every field, so submissions with it ticked are discarded.
Because the visitor's email is in a field named email, you can reply to the notification directly.
The CSS
.contact {
max-width: 560px;
margin: 40px auto;
padding: 32px;
background: #fff;
border: 1px solid #e6e6f0;
border-radius: 18px;
font-family: system-ui, sans-serif;
}
.contact h2 { margin: 0 0 4px; }
.contact p { margin: 0 0 24px; color: #64748b; }
.row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
.field { margin-bottom: 16px; }
.field label {
display: block;
margin-bottom: 6px;
font-weight: 600;
font-size: 14px;
}
.field input,
.field textarea {
width: 100%;
padding: 12px 14px;
font: inherit;
border: 1px solid #d4d4e0;
border-radius: 10px;
transition: border-color .15s, box-shadow .15s;
}
.field input:focus,
.field textarea:focus {
outline: none;
border-color: #645cec;
box-shadow: 0 0 0 3px rgba(100, 92, 236, .2);
}
.contact button {
width: 100%;
padding: 14px;
font: inherit;
font-weight: 700;
color: #fff;
background: #645cec;
border: 0;
border-radius: 10px;
cursor: pointer;
}
.contact button:hover { background: #4f46e5; }
.hp { display: none; }
@media (max-width: 560px) {
.row { grid-template-columns: 1fr; gap: 0; }
}
The two-column row collapses to a single column on small screens, so the form stays comfortable on phones.
Connecting it to your inbox
- Sign up for Formclick (the free plan includes 250 submissions a month).
- Create a form and copy its access key.
- Replace
YOUR_ACCESS_KEYin the HTML. - Publish the page and send a test message.
Every message is emailed to you and saved in your dashboard, so nothing is lost if an email lands in spam.
Showing a success message
The formclick.min.js script at the bottom submits the form in the background, shows a loading state on the button and displays a success or error message in place. If you would rather not use JavaScript, delete the script and add a redirect instead:
<input type="hidden" name="redirect" value="https://yourwebsite.com/thanks.html">
On the Free plan the thank-you page needs to be on the same website as the form; paid plans can redirect anywhere.
Optional extras
A topic dropdown
Useful if messages go to different people:
<div class="field">
<label for="topic">Topic</label>
<select id="topic" name="topic" required>
<option value="">Choose a topic…</option>
<option>Sales</option>
<option>Support</option>
<option>Partnerships</option>
</select>
</div>
A phone number
Make it optional — and use type="tel" so phones show a number pad:
<input id="phone" name="phone" type="tel" autocomplete="tel">
Consent checkbox
If you'll add people to a mailing list, ask clearly and separately:
<label>
<input type="checkbox" name="marketing_opt_in" value="yes">
Send me occasional product updates
</label>
Common contact form mistakes
- Using
mailto:as the action. It opens the visitor's email app (if they have one) instead of sending anything. Most people give up. - Missing
nameattributes. Fields without a name are silently dropped. - Placeholder-only labels. The hint disappears as soon as someone types.
- CAPTCHAs on every form. Start with a honeypot; add reCAPTCHA or Turnstile only if spam gets through.
- No confirmation. People resubmit when they aren't sure it worked.
Next steps
Prefer a finished design? Our contact form template is ready to copy, and there are variations for business inquiries and callback requests. To make sure it looks great on every screen, read How to Create a Responsive HTML Form.



