HTML contact form that sends email
Plain HTML cannot send email on its own — it needs somewhere to POST to. That is the entire problem this page solves: set the action to an endpoint and the ordinary form you already know how to write becomes a working contact form.
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">
<h2>Contact us</h2>
<label for="name">Name</label>
<input id="name" type="text" name="name" required>
<label for="email">Email</label>
<input id="email" type="email" name="email" required>
<label for="message">Message</label>
<textarea id="message" name="message" rows="4" required></textarea>
<!-- Land the visitor on your own page instead of ours -->
<input type="hidden" name="redirect" value="https://example.com/thank-you">
<button type="submit">Send message</button>
</form>body {
margin: 0;
padding: 32px 16px;
background: #fbfbfc;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
color: #18181b;
}
form {
display: flex;
flex-direction: column;
max-width: 420px;
margin: 0 auto;
}
h2 {
margin: 0 0 18px;
font-size: 20px;
}
label {
margin-bottom: 6px;
font-size: 13px;
font-weight: 600;
color: #3f3f46;
}
input,
textarea {
box-sizing: border-box;
font: inherit;
margin-bottom: 16px;
padding: 10px 12px;
color: #18181b;
background: #fff;
border: 1px solid #d4d4d8;
border-radius: 8px;
}
input:focus,
textarea:focus {
border-color: #2563eb;
outline: 2px solid rgba(37, 99, 235, 0.2);
}
textarea {
resize: vertical;
}
button {
padding: 11px 16px;
font: inherit;
font-weight: 600;
color: #fff;
background: #2563eb;
border: 0;
border-radius: 8px;
cursor: pointer;
}
button:disabled {
background: #93b4f5;
cursor: default;
}
/* The status line, shared by all three JavaScript versions. Keyed on the role
rather than a class, so it styles the element that is already announcing
itself to a screen reader. */
[role="status"] {
margin: 14px 0 0;
font-size: 14px;
text-align: center;
}
[role="status"]:empty {
display: none;
}
[role="status"].ok {
color: #16a34a;
}
[role="status"].bad {
color: #dc2626;
}Why HTML alone cannot send mail
HTML is markup. It can describe a form and it can tell the browser where to send it, but it has no way to open an SMTP connection — that has always required something on a server. The old answer was a PHP script; the modern one is to post to an endpoint that already does the job.
You may have seen action="mailto:you@example.com" suggested. It does not work in practice: it hands the submission to whatever desktop mail client the visitor has configured, which on most machines is none, and the ones that do open show the visitor a raw pile of form data to send manually.
The three attributes that matter
| Attribute | Value | What happens without it |
|---|---|---|
| action | your endpoint URL | The form posts back to the current page and nothing is sent |
| method | POST | Fields end up in the URL as a query string and are dropped |
| name | on every input | The field is not submitted at all — this is the usual cause of a missing field |
Landing on your own thank-you page
A plain form post is a navigation, so the browser has to arrive somewhere. Without configuration that is our confirmation page. The hidden redirect field overrides it per form, and you can set a default in the form settings instead so your markup never has to know:
<input type="hidden" name="redirect" value="https://example.com/thank-you">This is the version that always works
- It submits with JavaScript disabled, blocked by an extension, or simply not downloaded yet.
- It works in an email client preview, a text browser, and every no-code page builder that lets you paste raw HTML.
- There is no bundle, no hydration and nothing to go wrong between the click and the POST.
- The trade-off is the page navigation. If you need the visitor to stay put, add a submit handler — the markup does not change.
Questions about this contact form
- Can an HTML form send email without PHP?
- Not by itself, but it does not need PHP either. Point the action at a form endpoint and the sending happens there — you keep writing plain HTML and never deploy any server code of your own.
- Does action="mailto:" work for a contact form?
- Almost never. It depends on the visitor having a desktop mail client configured, and even then it shows them raw form data to send by hand. Most people see nothing happen at all.
- Why is one of my fields missing from the email?
- It has no name attribute. Browsers only submit inputs that have one — an id is for labels and CSS, not for submission. This is the single most common reason a field silently disappears.
- Can I host this on GitHub Pages or Netlify?
- Yes. There is nothing to run server-side, so any static host works — GitHub Pages, Netlify, Vercel, S3, or a folder on shared hosting. That is the whole point of putting the sending behind an endpoint.
Related examples
JavaScript contact form
Vanilla fetch with a real status message and proper error handling.
PHP contact form
The mail() version, and the reason most people should delete it.
Contact form without a backend
For static sites: no server, no database, no serverless function.
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.