splitforms.com
← Back to the journal

Bootstrap Contact Form: Responsive Template with Backend (2026)

Copy-paste Bootstrap 5 contact form template with working email delivery, validation, and spam protection. No PHP, no server, ready in 5 minutes.

Start free — 500 submissionsSee pricing →No card, no time limit. Pro is $5 per month.
Short answer
A Bootstrap 5 contact form with working email delivery, built-in validation, and spam protection — ready in 5 minutes. Use Bootstrap's form classes for responsive styling, point the action at splitforms (https://splitforms.com/api/submit), and you're done. No PHP, no SMTP, no server. Free for 500 submissions total.
Try it on your own form

Point any HTML form at one endpoint. 500 free submissions — no card, no time limit — and unlimited forms.

Create free account

Copy-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:

  1. JavaScript checks form validity with form.checkValidity()
  2. If invalid, Bootstrap shows red error messages via invalid-feedback divs
  3. If valid, the browser POSTs the form to https://splitforms.com/api/submit
  4. 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&apos;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-floating class for modern floating-label inputs
  • Dark mode: Add data-bs-theme="dark" to the <html> tag
  • Inline form: Use row g-3 align-items-center for 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

Site builders:
Frameworks:
Static site generators:

Ship your Bootstrap form today

Bootstrap form + splitforms backend = done.
Copy the template, add your access key, and start receiving submissions. Free for 500 submissions total. No credit card. No PHP. No server.
Get your free access key →

Keep reading

Related articles

More practical guidance from tutorials.

Browse the journal →
Tutorials

HTML Contact Form Code: Copy-Paste in 2026 (Templates)

Copy-paste HTML contact form code for 2026 — 10 ready-to-use templates with validation, spam…

22 min readRead →
Tutorials

How to Remove the Arrows From a Number Input (CSS, Tailwind, React)

Hide the number input spin buttons with ::-webkit-inner-spin-button and appearance: textfiel…

7 min readRead →
Tutorials

How to Change the Autofill Background Color of an Input (CSS, Tailwind)

Remove Chrome's yellow autofill background with input:-webkit-autofill, inset box-shadow, -w…

7 min readRead →

Explore this topic

Start with the overview, then move into focused guides.

OverviewWhat Is a Form Backend? (Complete Guide)Start here →GuideSelf-Hosted vs SaaS Form BackendRead →GuideForm Backend vs Form BuilderRead →GuideWhere Do Form Submissions Go?Read →ReferenceForm backend guideOpen →

Building forms with ChatGPT, Claude, Cursor, or v0? Connect the native MCP server and give your agent a production form backend.

Explore the MCP server →

Give your form a production backend.

One endpoint adds delivery, spam filtering, storage, and integrations. Start with 500 free submissions — no card, no time limit.

Create free accountRead the docs →
Secure checkoutSSL encryptionPrivacyProtected
VISAAMERICANEXPRESSstripe