Basic contact form

A minimal, accessible HTML contact form that emails you every message. Copy, paste your access key and it works on any static site.

This is the smallest contact form worth putting on a real site: three fields, proper labels, a spam trap and a send button. It needs no JavaScript and no server of your own. The browser posts it to SilentForms, the message is emailed to you, and the visitor lands on a thank-you page.

Get an access key on the access key page first. It only routes submissions to your inbox, so it is safe to leave in public HTML.

The complete page#

Save this as contact.html, replace the access key and open it in a browser:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Contact</title>
  <style>
    body {
      font-family: system-ui, sans-serif;
      line-height: 1.5;
      max-width: 32rem;
      margin: 3rem auto;
      padding: 0 1rem;
    }
    .field { margin-bottom: 1rem; }
    label { display: block; font-weight: 600; margin-bottom: 0.25rem; }
    input, textarea {
      width: 100%;
      box-sizing: border-box;
      padding: 0.6rem 0.75rem;
      border: 1px solid #8a8a8a;
      border-radius: 6px;
      font: inherit;
    }
    input:focus, textarea:focus {
      outline: 2px solid #2563eb;
      outline-offset: 1px;
    }
    button {
      padding: 0.65rem 1.25rem;
      border: 0;
      border-radius: 6px;
      background: #2563eb;
      color: #fff;
      font: inherit;
      font-weight: 600;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <h1>Contact us</h1>

  <form action="https://silentforms.com/api/submit" method="POST">
    <input type="hidden" name="accessKey" value="YOUR_ACCESS_KEY_HERE">

    <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 class="field">
      <label for="message">Message</label>
      <textarea id="message" name="message" rows="6" required></textarea>
    </div>

    <input type="checkbox" name="botcheck" style="display: none;" tabindex="-1" autocomplete="off">

    <button type="submit">Send message</button>
  </form>
</body>
</html>

Send yourself a message and check your inbox. If it is not there within a minute, look in the spam folder once and mark it as not spam.

What each part does#

The form element. action points at the submit endpoint and method="POST" is required: a GET request to the endpoint is refused with 405. No enctype is needed, since the default URL-encoded format is accepted.

The hidden accessKey input. This tells SilentForms whose inbox the submission belongs to. Without it you get "Access key is required."

Labels. Each label has a for attribute that matches an input's id. Screen readers announce the label when the field gets focus, and clicking the label focuses the field, which makes small inputs easier to hit on a phone. A placeholder is not a substitute: it disappears as soon as someone types.

name attributes. Browsers only send fields that have a name. Whatever you put there becomes the field label in the email, so name, email and message arrive as "name", "email" and "message". You can add any other field the same way, such as phone or company.

The email field. Naming the visitor's address email does two things: it shows in the submission, and it becomes the Reply-To address, so pressing Reply in your mail app answers the visitor directly. SilentForms checks it is a valid address and rejects the submission with "Email address is invalid." if not. See Reply-To address.

autocomplete. autocomplete="name" and autocomplete="email" let the browser offer saved details, so most visitors fill the form with two taps. They are standard tokens from the HTML specification; the field's name does not have to match.

required and type="email". The browser blocks submission and points at the problem before anything is sent. This is a convenience for visitors, not a security measure. For custom messages and styling, see Client-side validation.

The botcheck checkbox. A honeypot. People never see it, so they never tick it, and an unticked checkbox is not sent at all. Simple bots tick every box they find; when botcheck arrives with a value, the visitor still sees a normal success page but nothing is emailed. Keep tabindex="-1" so keyboard users never land on it. See Honeypot.

The button. A button with type="submit" inside the form submits it on click or when Enter is pressed in a text input.

What happens after Send#

On success the browser follows a redirect to the default thank-you page. To send visitors to a page on your own site instead, add a hidden redirect field with an absolute URL:

<input type="hidden" name="redirect" value="https://example.com/thanks.html">

If something goes wrong, for example an invalid email, the visitor is redirected to an error page that shows the reason. To stay on the page and show the result inline, submit with JavaScript instead: see AJAX form with JavaScript.

Next steps#