Phase 1 — HTML
Lesson 0003 • Beginner

HTML Forms & Tables

Every web app you'll ever build needs forms to collect data and tables to display it. This lesson teaches you both — and makes you dangerous enough to build a real contact page.

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.

Source: MDN — Your First Form

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
The URL where form data gets sent when submitted. Example: action="/api/contact"
method
GET = data in URL (search queries). POST = data in request body (passwords, form submissions). Default is GET.
basic-form.html
<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-input.html
<label for="user-name">Full Name</label>
<input type="text" id="user-name" name="name">
💡 The 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

<textarea>
Multi-line text input. Use for messages, descriptions, comments. Has rows and cols attributes.
<select> + <option>
Dropdown menu. Each choice is an <option> inside the <select>.
<button>
Preferred over <input type="submit">. Can contain text, icons, or HTML. Use type="submit" inside forms.
<fieldset> + <legend>
Groups related inputs visually and semantically. The <legend> is the group's title. Critical for accessibility.
form-elements.html
<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">
⚠️ Never Trust Client-Side Validation Alone HTML validation is a UX convenience — it helps users fix mistakes before submitting. But a malicious user can bypass it trivially (open DevTools → remove the 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-structure.html
<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

<table>
The table container. Everything goes inside it.
<thead>
Table head — contains the header row(s). Screen readers use this to announce column names.
<tbody>
Table body — the actual data rows.
<tfoot>
Table foot — summary rows, totals, footnotes.
<tr>
Table row. Contains <th> or <td> cells.
<th>
Table header cell. Bold by default. Use in <thead>. Tells screen readers "this is a column name."
<td>
Table data cell. A regular cell containing data.
colspan
Attribute that makes a cell span multiple columns. Example: colspan="3" merges 3 columns into one wide cell.

Source: MDN — HTML Table Basics

Interactive Practice Zone

Test your understanding of forms and tables.

Question 1: What attribute connects a <label> to its <input>?
Question 2: Which input type shows a date picker in the browser?
Question 3: What does the required attribute do on an input?
Question 4: In a table, which tag represents a header cell?
Question 5: What does colspan="3" do on a <td>?
Question 6: Why should you NOT use HTML tables for page layout?
0/6

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.

< action="/api/contact" method=" ">
  < ="user-email">Email</label>
  <input type=" " id="user-email" ="email" required>
  < name="message" rows="5"></textarea>
  < type="submit">Send</button>
</form>

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:

  1. Create a file called practices/lesson3-contact-page.html
  2. Use the semantic HTML structure from Lesson 2 (<header>, <main>, <footer>)
  3. Give it a proper <title>
  4. 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">
    • Section 2 — Pricing Table with:
      • A <table> with <thead>, <tbody>, and <tfoot>
      • At least 3 columns and 3 rows of data
      • A colspan footer row
  5. Add required attributes on the must-fill fields
  6. Open it in your browser — try submitting the form with empty required fields to see native validation
⚠️ Type From Understanding Do NOT copy the code examples above. Write it yourself. If you get stuck, re-read the relevant section, close your eyes, recall the structure, then type. The struggle is the learning.

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.