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

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

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
- Bootstrap
- Tailwind CSS
- Pico CSS: minimal, semantic, no classes required.