Building Contact Forms
Contact forms are essential for websites—they let visitors reach out to you directly. In this tutorial, you’ll learn how to build professional contact forms with various input types, validation, and best practices for user experience!
Why Contact Forms Matter
Contact forms provide a structured way for users to send you messages without exposing your email address to spam bots. They also allow you to collect exactly the information you need in a consistent format.
Benefits of contact forms:
- Spam protection — Email addresses aren’t publicly visible
- Structured data — You decide what information to collect
- Better UX — Users don’t need to open their email client
- Tracking — You can track form submissions and conversions
Basic Contact Form Structure
Every contact form needs these essential elements:
- Form container (
<form>) - Input fields (
<input>,<textarea>, etc.) - Labels for accessibility (
<label>) - Submit button (
<button>or<input type="submit">)
Here’s a simple contact form:
<!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>
</head>
<body>
<h1>Get in Touch</h1>
<form>
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="message">Message:</label>
<textarea id="message" name="message" rows="5" required></textarea>
<button type="submit">Send Message</button>
</form>
</body>
</html>Form Attributes Explained
The <form> Tag
<form action="/submit-form" method="post">
<!-- Form fields go here -->
</form>action— Where the form data is sent when submitted (URL or server endpoint)method— How data is sent:get(appends data to URL) orpost(sends in request body)
Best practice: Use method="post" for contact forms to keep data private.
Input Types
Different input types provide different interfaces and validation:
<!-- Text input -->
<input type="text" name="fullname" placeholder="John Doe">
<!-- Email input (validates email format) -->
<input type="email" name="email" placeholder="[email protected]">
<!-- Phone number -->
<input type="tel" name="phone" placeholder="(555) 123-4567">
<!-- Number input -->
<input type="number" name="age" min="1" max="120">
<!-- URL input -->
<input type="url" name="website" placeholder="https://example.com">
<!-- Date picker -->
<input type="date" name="preferred-date">Building a Complete Contact Form
Let’s build a professional contact form with styling:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Contact Form</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
padding: 20px;
}
.container {
max-width: 600px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
margin-bottom: 20px;
color: #333;
}
form {
display: flex;
flex-direction: column;
gap: 15px;
}
label {
font-weight: bold;
margin-bottom: 5px;
color: #555;
}
input, textarea, select {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
font-family: Arial, sans-serif;
}
input:focus, textarea:focus, select:focus {
outline: none;
border-color: #4CAF50;
}
textarea {
resize: vertical;
}
button {
background-color: #4CAF50;
color: white;
padding: 15px;
border: none;
border-radius: 4px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #45a049;
}
.required {
color: red;
}
</style>
</head>
<body>
<div class="container">
<h1>Contact Us</h1>
<form action="/submit-contact" method="post">
<div>
<label for="name">Full Name <span class="required">*</span></label>
<input type="text" id="name" name="name" required>
</div>
<div>
<label for="email">Email Address <span class="required">*</span></label>
<input type="email" id="email" name="email" required>
</div>
<div>
<label for="phone">Phone Number</label>
<input type="tel" id="phone" name="phone">
</div>
<div>
<label for="subject">Subject <span class="required">*</span></label>
<input type="text" id="subject" name="subject" required>
</div>
<div>
<label for="message">Message <span class="required">*</span></label>
<textarea id="message" name="message" rows="6" required></textarea>
</div>
<button type="submit">Send Message</button>
</form>
</div>
</body>
</html>Adding a Dropdown Select Menu
Sometimes you want users to choose from predefined options:
<label for="subject-type">Subject Type:</label>
<select id="subject-type" name="subject-type" required>
<option value="">-- Please choose --</option>
<option value="general">General Inquiry</option>
<option value="support">Technical Support</option>
<option value="sales">Sales Question</option>
<option value="feedback">Feedback</option>
</select>Best practices:
- Include a default empty option
- Use descriptive values
- Mark as required if needed
Form Validation
HTML5 provides built-in validation attributes:
<!-- Required field -->
<input type="text" name="name" required>
<!-- Minimum length -->
<input type="text" name="username" minlength="3" required>
<!-- Maximum length -->
<input type="text" name="bio" maxlength="500">
<!-- Pattern (regex) validation -->
<input type="text" name="zip" pattern="[0-9]{5}"
placeholder="12345" title="5-digit ZIP code">
<!-- Email validation (automatic) -->
<input type="email" name="email" required>
<!-- Number range -->
<input type="number" name="age" min="18" max="100" required>Checkbox and Radio Buttons
For yes/no questions or multiple choice:
<!-- Checkbox (multiple selections allowed) -->
<fieldset>
<legend>How can we help you?</legend>
<label>
<input type="checkbox" name="help" value="website">
Website Development
</label>
<label>
<input type="checkbox" name="help" value="design">
Design Services
</label>
<label>
<input type="checkbox" name="help" value="consulting">
Consulting
</label>
</fieldset>
<!-- Radio buttons (only one selection) -->
<fieldset>
<legend>Preferred contact method:</legend>
<label>
<input type="radio" name="contact-method" value="email" checked>
Email
</label>
<label>
<input type="radio" name="contact-method" value="phone">
Phone
</label>
<label>
<input type="radio" name="contact-method" value="text">
Text Message
</label>
</fieldset>Advanced Contact Form with All Features
Here’s a comprehensive contact form with multiple input types:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Advanced Contact Form</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 700px;
margin: 40px auto;
padding: 20px;
background-color: #f9f9f9;
}
form {
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #333;
}
input, textarea, select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
input:focus, textarea:focus, select:focus {
border-color: #007bff;
outline: none;
}
.checkbox-group, .radio-group {
display: flex;
flex-direction: column;
gap: 10px;
}
.checkbox-group label, .radio-group label {
font-weight: normal;
display: flex;
align-items: center;
gap: 8px;
}
.checkbox-group input, .radio-group input {
width: auto;
}
button {
background-color: #007bff;
color: white;
padding: 12px 30px;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
font-weight: bold;
}
button:hover {
background-color: #0056b3;
}
.required {
color: red;
}
</style>
</head>
<body>
<form action="/submit" method="post">
<h1>Contact Us</h1>
<p>We'd love to hear from you! Fill out the form below.</p>
<div class="form-group">
<label for="full-name">Full Name <span class="required">*</span></label>
<input type="text" id="full-name" name="full-name" required>
</div>
<div class="form-group">
<label for="email">Email Address <span class="required">*</span></label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="phone">Phone Number</label>
<input type="tel" id="phone" name="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"
placeholder="123-456-7890">
</div>
<div class="form-group">
<label for="company">Company Name</label>
<input type="text" id="company" name="company">
</div>
<div class="form-group">
<label for="inquiry-type">Type of Inquiry <span class="required">*</span></label>
<select id="inquiry-type" name="inquiry-type" required>
<option value="">-- Select One --</option>
<option value="general">General Question</option>
<option value="support">Technical Support</option>
<option value="sales">Sales Inquiry</option>
<option value="partnership">Partnership Opportunity</option>
</select>
</div>
<div class="form-group">
<label>Services Interested In:</label>
<div class="checkbox-group">
<label>
<input type="checkbox" name="services" value="web-dev">
Web Development
</label>
<label>
<input type="checkbox" name="services" value="design">
Design
</label>
<label>
<input type="checkbox" name="services" value="consulting">
Consulting
</label>
<label>
<input type="checkbox" name="services" value="marketing">
Marketing
</label>
</div>
</div>
<div class="form-group">
<label>Preferred Contact Method:</label>
<div class="radio-group">
<label>
<input type="radio" name="contact-pref" value="email" checked>
Email
</label>
<label>
<input type="radio" name="contact-pref" value="phone">
Phone
</label>
</div>
</div>
<div class="form-group">
<label for="message">Your Message <span class="required">*</span></label>
<textarea id="message" name="message" rows="6"
minlength="10" required></textarea>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="newsletter" value="yes">
Subscribe to our newsletter
</label>
</div>
<button type="submit">Send Message</button>
</form>
</body>
</html>Accessibility Best Practices
Always Use Labels
Labels help screen readers and make the entire area clickable:
Problematic example:
<input type="text" name="name">Improved example:
<label for="name">Name:</label>
<input type="text" id="name" name="name">Use Fieldsets for Related Inputs
Group related form controls together:
<fieldset>
<legend>Personal Information</legend>
<label for="first-name">First Name:</label>
<input type="text" id="first-name" name="first-name">
<label for="last-name">Last Name:</label>
<input type="text" id="last-name" name="last-name">
</fieldset>Provide Clear Error Messages
Use the title attribute or custom JavaScript to provide helpful error messages:
<input type="text"
name="username"
pattern="[a-zA-Z0-9]{3,15}"
title="Username must be 3-15 characters, letters and numbers only"
required>Common Mistakes to Avoid
Missing Name Attributes
Problematic example:
<input type="text" id="email">Improved example:
<input type="text" id="email" name="email">Without name, the data won’t be submitted!
Forgetting Labels
Problematic example:
<input type="text" name="phone" placeholder="Phone Number">Improved example:
<label for="phone">Phone Number:</label>
<input type="text" id="phone" name="phone" placeholder="555-1234">Placeholders disappear when typing—always use labels!
Not Using the Right Input Type
Problematic example:
<input type="text" name="email">Improved example:
<input type="email" name="email">Using the right type enables proper validation and mobile keyboard!
Form Submission Handling
Note: HTML forms alone can’t send emails. You need either:
- Server-side processing (PHP, Node.js, Python, etc.)
- Form handling service (Formspree, Netlify Forms, etc.)
- JavaScript with API (fetch, axios with backend)
Here’s an example with a form service:
<!-- Using Formspree (example) -->
<form action="https://formspree.io/f/YOUR_FORM_ID" method="POST">
<label for="email">Your Email:</label>
<input type="email" id="email" name="email" required>
<label for="message">Message:</label>
<textarea id="message" name="message" required></textarea>
<button type="submit">Send</button>
</form>Try It Yourself
Ready to practice? Try these challenges:
Challenge 1: Simple Feedback Form (Basic)
Create a feedback form with:
- Name and email fields
- Rating dropdown (1-5 stars)
- Comments textarea
- Submit button
- Basic CSS styling
Challenge 2: Job Application Form (Intermediate)
Build a job application form with:
- Personal information fields (name, email, phone)
- Resume upload (file input)
- Cover letter textarea
- Position dropdown menu
- Availability radio buttons (Full-time, Part-time, Contract)
- Submit and Clear buttons
Challenge 3: Multi-Step Registration (Advanced)
Create a registration form with:
- Multiple fieldsets for different sections
- Account information (username, password, confirm password)
- Personal details (name, birthday, address)
- Preferences (checkboxes for interests)
- All inputs properly validated
- Professional styling with focus states
- Responsive design for mobile
What You Learned
Congratulations! You now know:
- How to build contact forms with various input types
- How to use labels, placeholders, and validation
- How to create checkboxes, radio buttons, and dropdowns
- Form accessibility best practices
- How to style forms for better user experience
Next Steps
Now that you can create contact forms, explore these related tutorials:
- Forms — Learn basic form fundamentals
- Accessible Forms — Deep dive into form accessibility
- Semantic HTML — Use proper HTML5 elements
- Complete Website — Build a full site with contact form
Want to experiment with forms? Try our interactive HTML editor!