action at splitforms (https://splitforms.com/api/submit), and you're done. No PHP, no SMTP, no server. Free for 500 submissions total.Point any HTML form at one endpoint. 500 free submissions — no card, no time limit — and unlimited forms.
Create free accountCopy-paste Bootstrap 5 contact form
Here's the full template. Include Bootstrap 5 CSS/JS, add your splitforms access key, and ship.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Contact Us</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-8 col-lg-6">
<h1 class="mb-4">Contact Us</h1>
<form
action="https://splitforms.com/api/submit"
method="POST"
class="needs-validation"
novalidate
>
<!-- splitforms config -->
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input type="hidden" name="subject" value="New contact from yoursite.com" />
<input type="hidden" name="redirect" value="https://yoursite.com/thanks" />
<!-- Honeypot spam trap -->
<input name="botcheck" type="checkbox" style="display:none" tabindex="-1" />
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input
type="text"
class="form-control"
id="name"
name="name"
required
minlength="2"
/>
<div class="invalid-feedback">Please enter your name.</div>
</div>
<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="subject" class="form-label">Subject</label>
<select class="form-select" id="subject" name="subject_type">
<option value="general">General inquiry</option>
<option value="sales">Sales question</option>
<option value="support">Technical support</option>
<option value="partnership">Partnership</option>
</select>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea
class="form-control"
id="message"
name="message"
rows="5"
required
minlength="10"
></textarea>
<div class="invalid-feedback">Please enter a message (at least 10 characters).</div>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="consent" name="consent" required />
<label class="form-check-label" for="consent">
I agree to be contacted regarding my inquiry.
</label>
<div class="invalid-feedback">You must agree to be contacted.</div>
</div>
<button type="submit" class="btn btn-primary btn-lg w-100">
Send Message
</button>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Bootstrap 5 custom validation
(function() {
'use strict';
var form = document.querySelector('.needs-validation');
form.addEventListener('submit', function(event) {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
})();
</script>
</body>
</html>How it works
The form uses Bootstrap's needs-validation class for client-side validation. When the user clicks submit:
- JavaScript checks form validity with
form.checkValidity() - If invalid, Bootstrap shows red error messages via
invalid-feedbackdivs - If valid, the browser POSTs the form to
https://splitforms.com/api/submit - splitforms filters spam (honeypot + rule-based scorer), sends the email, and redirects to your thank-you page
No server-side code. No PHP. No SMTP. Works on GitHub Pages, S3, Vercel, Netlify, or any static host.
AJAX version (no page reload)
Want to submit without a page reload? Add a fetch handler:
<form id="contact-form" class="needs-validation" novalidate>
<!-- same fields as above -->
</form>
<script>
var form = document.getElementById('contact-form');
var button = form.querySelector('button[type="submit"]');
form.addEventListener('submit', async function(e) {
e.preventDefault();
if (!form.checkValidity()) {
form.classList.add('was-validated');
return;
}
button.disabled = true;
button.innerHTML = '<span class="spinner-border spinner-border-sm" role="status"></span> Sending...';
try {
var response = await fetch('https://splitforms.com/api/submit', {
method: 'POST',
body: new FormData(form),
});
if (response.ok) {
form.reset();
form.classList.remove('was-validated');
form.insertAdjacentHTML('beforebegin',
'<div class="alert alert-success">Thanks! We\'ll get back to you within 24 hours.</div>'
);
} else {
throw new Error('Server error');
}
} catch (error) {
form.insertAdjacentHTML('beforebegin',
'<div class="alert alert-danger">Something went wrong. Please try again or email hello@splitforms.com</div>'
);
} finally {
button.disabled = false;
button.innerHTML = 'Send Message';
}
});
</script>This version uses Bootstrap's spinner component for the loading state and Bootstrap alerts for success/error messages.
React-Bootstrap version
Using react-bootstrap? Here's the same form as a React component:
'use client';
import { useState } from 'react';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import Alert from 'react-bootstrap/Alert';
export default function BootstrapContactForm() {
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
const [validated, setValidated] = useState(false);
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const form = e.currentTarget;
if (!form.checkValidity()) {
setValidated(true);
return;
}
setStatus('loading');
try {
const res = await fetch('https://splitforms.com/api/submit', {
method: 'POST',
body: new FormData(form),
});
if (!res.ok) throw new Error();
setStatus('success');
setValidated(false);
form.reset();
} catch {
setStatus('error');
}
}
return (
<>
{status === 'success' && (
<Alert variant="success">Thanks! We'll be in touch within 24 hours.</Alert>
)}
{status === 'error' && (
<Alert variant="danger">Something went wrong. Please try again.</Alert>
)}
<Form noValidate validated={validated} onSubmit={handleSubmit}>
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<Form.Group className="mb-3">
<Form.Label>Name</Form.Label>
<Form.Control name="name" required type="text" />
<Form.Control.Feedback type="invalid">Please enter your name.</Form.Control.Feedback>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Email</Form.Label>
<Form.Control name="email" required type="email" />
<Form.Control.Feedback type="invalid">Please enter a valid email.</Form.Control.Feedback>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Message</Form.Label>
<Form.Control name="message" required as="textarea" rows={5} />
<Form.Control.Feedback type="invalid">Please enter a message.</Form.Control.Feedback>
</Form.Group>
<Button type="submit" variant="primary" size="lg" className="w-100"
disabled={status === 'loading'}>
{status === 'loading' ? 'Sending...' : 'Send Message'}
</Button>
</Form>
</>
);
}Customizing the form
Common modifications:
- Two-column layout: Wrap name and email in
<div class="row"><div class="col-md-6 mb-3"> - File upload: Add
<input type="file" name="attachment" class="form-control" />— splitforms handles file attachments - Floating labels: Use
form-floatingclass for modern floating-label inputs - Dark mode: Add
data-bs-theme="dark"to the<html>tag - Inline form: Use
row g-3 align-items-centerfor horizontal layouts
Spam protection (no CAPTCHA needed)
The hidden botcheck honeypot field catches most bots. splitforms adds rule-based spam scoring on top — analyzing link density, spam phrases, and submission velocity to catch the vast majority of spam without any CAPTCHA.
No reCAPTCHA. No hCaptcha. No Turnstile. No annoying puzzles. Just clean protection that's GDPR-compliant and invisible to real users.
Frequently asked questions
How do I create a Bootstrap contact form?
Use Bootstrap 5 form classes (mb-3, form-label, form-control, btn btn-primary) for styling, then point the form's action attribute at a hosted backend like splitforms (https://splitforms.com/api/submit) for email delivery. No PHP or server-side code required. The full template is ready in 5 minutes.
Does Bootstrap 5 have a built-in contact form component?
Bootstrap 5 provides form styling classes (form-control, form-select, input-group) but does not include a backend for processing submissions. You need a form backend — splitforms is free for 500 submissions total and works seamlessly with Bootstrap-styled forms.
How do I validate a Bootstrap contact form?
Use Bootstrap 5's built-in validation classes (was-validated, invalid-feedback, valid-feedback) combined with HTML5 constraints (required, type=email, pattern). Add the novalidate attribute to the form tag and use JavaScript to toggle the was-validated class on submit.
Can I use a Bootstrap contact form without PHP?
Yes. Point your form's action at https://splitforms.com/api/submit with your access key. splitforms handles email delivery, spam filtering, and storage. No PHP, no SMTP, no server required — works on any static host.
How do I make a Bootstrap contact form responsive?
Bootstrap 5 is responsive by default. Use the grid system (row, col-md-6) for side-by-side fields on desktop and stacked fields on mobile. The form-control class makes inputs full-width and touch-friendly automatically.
Add a contact form to another platform
Ship your Bootstrap form today
Keep reading
- HTML contact form code templates (2026)
- AJAX contact form guide
- Tailwind CSS form validation
- Contact form without PHP
- Sign up for free — 500 submissions total, Bootstrap-ready.