CSS frameworks
A contact form styled with Bootstrap
Bootstrap's form components handle the layout and the validation styling; the missing piece is the endpoint. This is a standard Bootstrap 5 form - form-control, form-label, invalid-feedback, the was-validated class - pointed at a WebForms endpoint so it actually delivers.
Setup
Copy your endpoint
Create a form in the dashboard.
Paste the markup
Standard Bootstrap 5 classes, no custom CSS.
Optionally add validation
The second snippet uses Bootstrap's own was-validated flow before allowing the submit through.
Bootstrap examples
Swap in your own endpoint and these run as-is.
Bootstrap 5 with floating labels.
<form action="https://send.webforms.to/wft_your_key" method="POST" class="mx-auto" style="max-width: 32rem">
<div class="form-floating mb-3">
<input type="text" class="form-control" id="name" name="name"
placeholder="Ada Lovelace" required />
<label for="name">Name</label>
</div>
<div class="form-floating mb-3">
<input type="email" class="form-control" id="email" name="email"
placeholder="you@example.com" required />
<label for="email">Email address</label>
</div>
<div class="form-floating mb-3">
<textarea class="form-control" id="message" name="message"
placeholder="Message" style="height: 8rem" required></textarea>
<label for="message">Message</label>
</div>
<input type="hidden" name="_next" value="https://example.com/thanks" />
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off"
class="d-none" aria-hidden="true" />
<button class="btn btn-primary w-100 py-2" type="submit">Send message</button>
</form>With Bootstrap's validation styles and an AJAX submit, so the visitor stays on the page.
<form id="contact" action="https://send.webforms.to/wft_your_key" method="POST" class="needs-validation" novalidate>
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" name="email" required />
<div class="invalid-feedback">Please enter a valid email address.</div>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea class="form-control" id="message" name="message" rows="4" required></textarea>
<div class="invalid-feedback">Don’t forget the message.</div>
</div>
<button class="btn btn-primary" type="submit">Send</button>
<div id="result" class="mt-3"></div>
</form>
<script>
const form = document.getElementById("contact");
const result = document.getElementById("result");
form.addEventListener("submit", async (event) => {
event.preventDefault();
event.stopPropagation();
form.classList.add("was-validated");
if (!form.checkValidity()) return;
const res = await fetch(form.action, {
method: "POST",
headers: { accept: "application/json" },
body: new FormData(form),
});
const data = await res.json();
result.className = data.ok ? "alert alert-success mt-3" : "alert alert-danger mt-3";
result.textContent = data.ok ? "Thanks, we got it." : data.message;
if (data.ok) {
form.reset();
form.classList.remove("was-validated");
}
});
</script>Bootstrap form FAQ
The markup is Bootstrap 5. For v4, swap form-floating for form-group and the classes behave the same - the endpoint side is identical either way.
Related guides
Ready to wire up your Bootstrap form?
Free for 300 submissions a month. Endpoint in under a minute, no card required.
Start free