Skip to content

Form styling

With Formspark you get to bring your own HTML and CSS.

On this page you'll find tips, tricks and links to help you style your forms.

Simple vertical layout

Simple vertical layout

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      .vertical-form {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        max-width: 500px;
      }
    </style>
  </head>
  <body>
    <form
      class="vertical-form"
      action="https://submit-form.com/your-form-id"
      method="POST"
    >
      <label for="first-name">First name</label>
      <input id="first-name" name="first-name" type="text" />
      <label for="last-name">Last name</label>
      <input id="last-name" name="last-name" type="text" />
      <label for="message">Message</label>
      <textarea id="message" name="message" cols="15" rows="5"></textarea>
      <button type="submit">Submit</button>
    </form>
  </body>
</html>

Accessible form

Pair every input with a <label for>, give focused fields a visible outline, and never rely on placeholder text as a label.

html
<style>
  .accessible-form {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-width: 500px;
    font-family: system-ui, sans-serif;
  }
  .accessible-form label {
    font-weight: 600;
  }
  .accessible-form :is(input, textarea) {
    padding: 0.5rem;
    border: 1px solid #ccc;
    border-radius: 4px;
  }
  .accessible-form :is(input, textarea):focus-visible {
    outline: 3px solid #707ee7;
    outline-offset: 2px;
  }
</style>

<form
  class="accessible-form"
  action="https://submit-form.com/your-form-id"
  method="POST"
>
  <label for="email">Email</label>
  <input id="email" name="email" type="email" required />

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="5" required></textarea>

  <button type="submit">Send</button>
</form>

Tailwind CSS

html
<form
  class="mx-auto flex max-w-md flex-col gap-3"
  action="https://submit-form.com/your-form-id"
  method="POST"
>
  <label for="email" class="font-semibold">Email</label>
  <input
    id="email"
    name="email"
    type="email"
    required
    class="rounded border border-gray-300 p-2 focus-visible:outline focus-visible:outline-2 focus-visible:outline-indigo-500"
  />

  <label for="message" class="font-semibold">Message</label>
  <textarea
    id="message"
    name="message"
    rows="5"
    required
    class="rounded border border-gray-300 p-2 focus-visible:outline focus-visible:outline-2 focus-visible:outline-indigo-500"
  ></textarea>

  <button
    type="submit"
    class="rounded bg-indigo-600 px-4 py-2 font-semibold text-white hover:bg-indigo-700"
  >
    Send
  </button>
</form>

Add an asterisk to required field labels

Required field label asterisk

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      label.required:after {
        content: "*";
        color: red;
      }
    </style>
  </head>
  <body>
    <form action="https://submit-form.com/your-form-id" method="POST">
      <label for="first-name" class="required">First name</label>
      <input id="first-name" name="first-name" type="text" required />
      <label for="last-name">Last name</label>
      <input id="last-name" name="last-name" type="text" />
      <button type="submit">Submit</button>
    </form>
  </body>
</html>

Success and error states (AJAX)

When you submit via AJAX, you control the post-submission UI yourself. A common pattern is to swap the form for a thank-you message on success and show an inline error on failure.

html
<form id="contact" action="https://submit-form.com/your-form-id" method="POST">
  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>
  <button type="submit">Send</button>
  <p id="error" hidden>Something went wrong. Please try again.</p>
</form>

<div id="thanks" hidden>Thanks! We received your message.</div>

<script>
  const form = document.getElementById("contact");
  const error = document.getElementById("error");
  const thanks = document.getElementById("thanks");

  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    error.hidden = true;
    const button = form.querySelector("button");
    button.disabled = true;
    button.textContent = "Sending...";
    try {
      const response = await fetch(form.action, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
        },
        body: JSON.stringify(Object.fromEntries(new FormData(form))),
      });
      if (!response.ok) throw new Error();
      form.hidden = true;
      thanks.hidden = false;
    } catch {
      error.hidden = false;
      button.disabled = false;
      button.textContent = "Send";
    }
  });
</script>

CSS frameworks