1. Why Forms Matter
Without forms, the web is a one-way street — users can only read. Forms turn visitors into participants: login screens, contact forms, search bars, checkout flows, newsletter sign-ups. Every SaaS product you'll build starts with a <form>.
When a user submits a form, the browser bundles all the input values and sends them to a server. You'll learn the server side later (Node.js + Express), but for now, focus on the HTML structure.
2. The <form> Element
A form is a container. Every input, label, and button lives inside it. The two essential attributes are:
Form Attributes
action="/api/contact"GET = data in URL (search queries). POST = data in request body (passwords, form submissions). Default is GET.<form action="/api/contact" method="POST">
<!-- inputs go here -->
</form>
3. Inputs & Labels — The Core Duo
An <input> alone is a mystery box. Users don't know what to type. A <label> tells them. Always pair them.
The Label-Input Connection
The for attribute on a <label> must match the id on the <input>. This does three things: (1) clicking the label focuses the input, (2) screen readers announce the label when the input is focused, (3) it's a legal accessibility requirement for professional websites.
<label for="user-name">Full Name</label>
<input type="text" id="user-name" name="name">
name Attribute
The name is what the server receives as the key. If name="email" and the user types hello@example.com, the server gets { email: "hello@example.com" }. No name = the input's value is never sent.
4. Common Input Types
The type attribute changes the input's behavior, keyboard, and validation. Memorize these — you'll use them constantly:
| Type | What It Does | Mobile Keyboard |
|---|---|---|
text |
Single-line text (names, usernames) | Standard keyboard |
email |
Validates email format, shows @ key | Email keyboard |
password |
Hides characters with dots | Standard keyboard |
number |
Only accepts numbers, shows +/- spinners | Numeric keypad |
tel |
Phone number (no validation, but right keyboard) | Phone keypad |
url |
Validates URL format | .com shortcut key |
date |
Date picker (browser-native) | Date picker UI |
checkbox |
Toggle on/off (agree to terms, preferences) | — |
radio |
Choose ONE from a group (same name) |
— |
submit |
Submits the form | — |
Source: MDN — Input Types (complete list)
5. Beyond Inputs: <textarea>, <select>, and <button>
Other Form Elements
rows and cols attributes.<option> inside the <select>.<input type="submit">. Can contain text, icons, or HTML. Use type="submit" inside forms.<legend> is the group's title. Critical for accessibility.<form action="/api/contact" method="POST">
<fieldset>
<legend>Your Details</legend>
<label for="name">Full Name</label>
<input type="text" id="name" name="name" required>
<label for="email">Email Address</label>
<input type="email" id="email" name="email" required>
</fieldset>
<fieldset>
<legend>Your Message</legend>
<label for="subject">Subject</label>
<select id="subject" name="subject">
<option value="">Select a topic...</option>
<option value="hire">Hire Me</option>
<option value="freelance">Freelance Project</option>
<option value="other">Other</option>
</select>
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" placeholder="Tell me about your project..."></textarea>
</fieldset>
<button type="submit">Send Message</button>
</form>
6. Validation Attributes — Free Error Checking
HTML gives you built-in validation for free. No JavaScript needed. The browser checks these rules when the user clicks submit:
| Attribute | What It Does | Example |
|---|---|---|
required |
Field cannot be empty | <input required> |
minlength |
Minimum character count | <input minlength="3"> |
maxlength |
Maximum character count | <input maxlength="100"> |
min / max |
Number range limits | <input type="number" min="1" max="10"> |
pattern |
Custom regex pattern | <input pattern="[0-9]{10}"> |
placeholder |
Hint text (not a substitute for a label!) | <input placeholder="e.g. John"> |
required attribute). You must always validate on the server too. You'll learn server-side validation when we reach Node.js + Express.
Source: MDN — Client-Side Form Validation
7. HTML Tables — Displaying Structured Data
Tables are for tabular data — anything that belongs in rows and columns: pricing plans, schedules, leaderboards, order histories. They are NOT for page layout (that's what CSS Flexbox and Grid are for — you'll learn those next).
When to Use a Table
Ask: "Would this data make sense in a spreadsheet?" If yes → use a <table>. If you're just arranging elements side by side → use CSS, not a table.
8. Table Anatomy
<table>
<thead>
<tr>
<th>Plan</th>
<th>Price/month</th>
<th>Features</th>
</tr>
</thead>
<tbody>
<tr>
<td>Free</td>
<td>$0</td>
<td>3 projects, community support</td>
</tr>
<tr>
<td>Pro</td>
<td>$19</td>
<td>Unlimited projects, priority support</td>
</tr>
<tr>
<td>Enterprise</td>
<td>$99</td>
<td>Custom solutions, dedicated support</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3">All plans include a 14-day free trial</td>
</tr>
</tfoot>
</table>
Table Elements Glossary
<th> or <td> cells.<thead>. Tells screen readers "this is a column name."colspan="3" merges 3 columns into one wide cell.Source: MDN — HTML Table Basics
Interactive Practice Zone
Test your understanding of forms and tables.
<label> to its <input>?required attribute do on an input?colspan="3" do on a <td>?Quiz Completed!
Come back and retry this quiz tomorrow — spaced repetition builds permanent knowledge.
9. Fill in the Blank: Write a Contact Form
Complete this form structure from memory. Each blank is one word or tag name.
10. Build Challenge: Contact Page + Pricing Table
Time to build something real. Create a file that contains both a contact form and a pricing table. Here's your spec:
- Create a file called
practices/lesson3-contact-page.html - Use the semantic HTML structure from Lesson 2 (
<header>,<main>,<footer>) - Give it a proper
<title> - In
<main>, build two sections:- Section 1 — Contact Form with:
- A
<fieldset>+<legend>for "Personal Info" - Name input (
type="text",required) - Email input (
type="email",required) - Phone input (
type="tel") - A
<select>dropdown for the subject - A
<textarea>for the message - A
<button type="submit">
- A
- Section 2 — Pricing Table with:
- A
<table>with<thead>,<tbody>, and<tfoot> - At least 3 columns and 3 rows of data
- A
colspanfooter row
- A
- Section 1 — Contact Form with:
- Add
requiredattributes on the must-fill fields - Open it in your browser — try submitting the form with empty required fields to see native validation
Primary Source: Read the complete MDN: Web Forms Guide for a deeper dive into every form element and its attributes.
Finished the build? Stuck on something? Come back and show me your code — I'll review it and tell you what's next.