MGU Computer Science Series — Web Development: HTML, CSS, and JavaScript
Part II: HTML — Structure and Meaning
Lists · Tables · Forms · Inputs · Accessibility
Chapter 9 of 30
9
MGU Computer Science Series  ·  Web Development: HTML, CSS, and JavaScript  ·  Library Textbook Edition

Chapter 9:
Lists, Tables, Forms,
and Inputs

How HTML groups related items, presents tabular data, and collects information from users — and why accessibility is built into these structures from the first line of code

■ Part II of VII ■

■ 10 Sections  •  Chapter 9 of 30 ■

Builds on Chapters 5–8 — HTML documents, semantic text, links, and media

Chapter Introduction and Learning Objectives

Open almost any real website and you will find the same three content structures appearing again and again: a list of links in a navigation menu, a table of prices or scores or scheduled events, and a form asking for a name, an email address, or a message. These are not decorative choices. They are some of the oldest and most important structural patterns in HTML, and they exist because human information naturally groups itself into collections, grids, and questions that need answers.

This chapter teaches all three. You will learn how to group related items with ordered, unordered, and description lists. You will learn how to build tables that present data clearly, with headers that a screen reader can announce correctly. And you will learn how to build forms — the part of the web that turns a one-way page into a two-way conversation between a website and the person using it. Throughout, one idea will return again and again: HTML structures carry meaning, and that meaning is what makes a page usable by everyone, not just by people who can see a bulleted dot or a boxed-in grid.

Opening Question

A recipe page lists ingredients and then lists steps. A class schedule shows days, times, and rooms in a grid. A contact page asks for a name, an email address, and a message, then waits for the visitor to click a button. What do these three things have in common? Each one takes loosely related pieces of content — items, data points, or questions — and gives them a structure a browser can understand, a screen reader can announce, and CSS can style consistently. By the end of this chapter, you will know how to build all three, and you will understand why the structure matters as much as the content inside it.

10Sections
11Objectives
23Key Terms
30Total Chapters

Learning Objectives

By the end of this chapter, you should be able to:

  1. 1Explain why lists, tables, and forms require dedicated HTML structures rather than plain-text formatting.
  2. 2Distinguish between unordered lists, ordered lists, and description lists, and choose the correct one for given content.
  3. 3Correctly nest lists according to HTML's structural rules.
  4. 4Build a data table using <table>, <tr>, <th>, and <td>.
  5. 5Improve table accessibility using the scope attribute, <caption>, and table sectioning elements.
  6. 6Use colspan and rowspan to merge table cells correctly.
  7. 7Explain the purpose of the <form> element and its action and method attributes.
  8. 8Associate labels with form inputs using both explicit and implicit techniques.
  9. 9Select the appropriate <input> type, <textarea>, or <select> element for a given kind of data.
  10. 10Distinguish between checkboxes and radio buttons, and group related controls correctly with <fieldset> and <legend>.
  11. 11Build a complete, accessible contact form following the conventions introduced in this chapter.

Sections at a Glance

Sections 9.1 – 9.3
Lists: Grouping Related Content
Unordered Lists · Ordered Lists · Description Lists · Nesting

Lists for Structured Content

When you read a recipe, a schedule, a course syllabus, or a shopping cart, you are reading a list. Lists are one of the oldest and most natural ways human beings organize information. HTML reflects this. It gives you three different list elements depending on what kind of grouping you need, and each one carries a specific kind of meaning.

Before HTML had list elements, some developers made "lists" by typing items on separate lines and adding dashes or numbers manually as plain text. This approach looks correct to a human eye, but it tells a browser nothing about the structure. A screen reader cannot identify a manually typed dash followed by text as a list item. A search engine cannot tell that the ten lines you typed are related. CSS cannot easily target "the third item in this list" if the browser does not know a list is there.

HTML lists solve this by wrapping related items in a container element and marking each item with a consistent element. When the browser reads a list, it knows the items belong together. When a screen reader reaches a list, it announces how many items the list contains and lets the user navigate between them. When CSS applies a style to a list, it can target every item with one rule.

List Type 1
Unordered List
For items where sequence does not matter. Created with <ul>. Displays with bullet points by default.
List Type 2
Ordered List
For items where sequence matters. Created with <ol>. Displays with automatic numbering by default.
List Type 3
Description List
For terms paired with definitions or explanations. Created with <dl>, <dt>, and <dd>.

Each type has a different element, but they share a common idea: the list is a container, and each item inside it is marked individually. The next two sections work through each list type in detail.

Ordered and Unordered Lists

Unordered Lists

An unordered list is a collection of items where the order is not meaningful. A list of ingredients, a list of features on a product page, a set of links in a navigation menu — these are all unordered because the items could be rearranged without changing what the list means.

The element for an unordered list is <ul>. Each item inside the list uses the <li> element, which stands for list item. The browser displays each item with a bullet point by default.

HTML — Unordered List
<ul>
  <li>HTML</li>
  <li>CSS</li>
  <li>JavaScript</li>
</ul>

The bullet style is a browser default. CSS can change it to a different symbol, remove it entirely, or replace it with a custom icon — you will work with CSS list styling in Part III. For now, focus on the structure.

Notice the indentation. The <li> elements are indented inside the <ul> element. This indentation is a convention, not a technical requirement, but it is a strong convention for good reason: it makes the parent-child relationship visible at a glance. The <ul> element is the parent. Each <li> element is its child.

Ordered Lists

An ordered list is a collection of items where the sequence matters. A numbered set of steps, a ranking, a recipe with a specific procedure — these need order because doing step three before step one would give a different, and probably wrong, result.

The element for an ordered list is <ol>. Items still use <li>.

HTML — Ordered List
<ol>
  <li>Open your text editor.</li>
  <li>Create a new file called index.html.</li>
  <li>Type the HTML document skeleton.</li>
  <li>Save the file.</li>
  <li>Open the file in your browser.</li>
</ol>
Why Automatic Numbering Matters

The browser generates the numbers for an ordered list automatically. You do not type them. If you later insert a new step between step two and step three, the browser renumbers every step correctly. If you had typed the numbers manually as plain text, you would have to update every number by hand.

Nested Lists

Lists can be nested. An item in an outer list can contain its own inner list. This is useful for outlines, sub-steps, and hierarchical content. The inner list must be placed inside an <li> element of the outer list — never directly inside the outer list container.

Correct Nesting
<ol>
  <li>Step one
    <ul>
      <li>Sub-step A</li>
      <li>Sub-step B</li>
    </ul>
  </li>
  <li>Step two</li>
</ol>
Incorrect Nesting — Do Not Do This
<ol>
  <li>Step one</li>
  <ul>
    <li>Sub-step A</li>
  </ul>
  <li>Step two</li>
</ol>
Why the Incorrect Version Fails

The incorrect version places a <ul> directly inside an <ol> rather than inside an <li>. Browsers may still render it visually, but the structure is invalid HTML, and assistive technologies may misread the relationship between the steps and the sub-items.

What <li> Can Contain

A list item can contain plain text, but it can also contain other elements: links, images, headings at an appropriate level, paragraphs, and even other lists. The <li> element is a container.

HTML — A List of Links
<ul>
  <li><a href="about.html">About Us</a></li>
  <li><a href="lessons.html">Lessons</a></li>
  <li><a href="contact.html">Contact</a></li>
</ul>

This is exactly how navigation menus are structured in real websites. The navigation bar on a finished site looks like a horizontal row of links styled with CSS — but underneath, it is almost always an unordered list of anchor elements.

Description Lists

A description list is a structure for pairing terms with their definitions or explanations. A glossary, a FAQ section, a specification sheet, or a product feature list with labels and values — these are all good candidates for a description list.

The element for a description list is <dl>. Inside it, each term uses <dt> (description term), and each definition uses <dd> (description detail).

HTML — Description List
<dl>
  <dt>HTML</dt>
  <dd>HyperText Markup Language. The structural language of web pages.</dd>

  <dt>CSS</dt>
  <dd>Cascading Style Sheets. The language used to control visual presentation.</dd>

  <dt>JavaScript</dt>
  <dd>A programming language that runs in the browser to add interactivity.</dd>
</dl>

By default, browsers display <dt> terms on their own line and indent the <dd> definitions below them, though the exact appearance varies by browser. One term can have multiple definitions, and one definition block can follow multiple terms:

HTML — One Definition, Two Terms
<dl>
  <dt>Viewport</dt>
  <dt>Browser viewport</dt>
  <dd>The visible area of a web page inside a browser window.</dd>
</dl>
When to Reach for a Description List

Description lists are used less often than <ul> and <ol>, but they carry specific semantic meaning that cannot be replicated well with other elements. When your content is truly a set of term-definition pairs, <dl> communicates that relationship to browsers and assistive technologies.

Sections 9.4 – 9.5
Tables: Presenting Data in Rows and Columns
Table Structure · Headers · Captions · Sectioning · Spanning Cells

Tables for Data

A table is a grid of rows and columns used to display data where the relationship between values across both rows and columns is meaningful. A class schedule, a comparison of pricing plans, a grade sheet, a sports standings chart, a dataset of historical measurements — these are data that belong in a table.

Tables Are Not for Layout

In the early years of the web, before CSS provided powerful layout tools, developers used tables to control where content appeared on the page. They put navigation in one table cell and main content in another. This practice was abandoned long ago. CSS handles layout. Tables carry data. Mixing these roles produces broken structure, poor accessibility, and code that is very difficult to maintain.

The Basic Table Structure

A table uses four core elements working together:

  • <table> wraps the entire table.
  • <tr> defines a table row.
  • <th> defines a header cell. By default, browsers bold and center the text inside it.
  • <td> defines a data cell, also called a regular cell.
HTML — A Simple Data Table
<table>
  <tr>
    <th>Student</th>
    <th>Score</th>
    <th>Grade</th>
  </tr>
  <tr>
    <td>Amara</td>
    <td>94</td>
    <td>A</td>
  </tr>
  <tr>
    <td>Brendan</td>
    <td>81</td>
    <td>B</td>
  </tr>
  <tr>
    <td>Chloé</td>
    <td>76</td>
    <td>C</td>
  </tr>
</table>
Reading the Structure
How to read a table in your mind
  • Row 1Three <th> elements — the header row, labeling Student, Score, and Grade.
  • Row 2Three <td> elements — the first data row, representing Amara.
  • RenderingWithout CSS, this table displays as a plain grid with left-aligned text in data cells and bold, centered text in header cells. Part III covers styling tables with CSS.
Keep Rows Complete

Every row should have the same number of cells unless you are deliberately spanning cells, covered in the next section. A table where rows have different numbers of cells will often display incorrectly and is confusing to read.

Table Headers, Captions, and Sections

The scope Attribute on Header Cells

Headers identify what a column or row means. But a browser and a screen reader cannot always determine whether a <th> cell applies to the column below it or the row beside it. The scope attribute makes this explicit.

HTML — scope="col"
<table>
  <tr>
    <th scope="col">Student</th>
    <th scope="col">Score</th>
    <th scope="col">Grade</th>
  </tr>
  <tr>
    <td>Amara</td>
    <td>94</td>
    <td>A</td>
  </tr>
</table>

Using scope="col" tells assistive technologies that this header applies to all cells in its column. You can also use scope="row" when the header applies to cells in its row, which is common in tables that have both row and column headers.

HTML — scope="col" and scope="row" Together
<table>
  <tr>
    <th scope="col">Day</th>
    <th scope="col">Topic</th>
    <th scope="col">Assignment</th>
  </tr>
  <tr>
    <th scope="row">Monday</th>
    <td>HTML Lists</td>
    <td>Build a glossary page</td>
  </tr>
  <tr>
    <th scope="row">Wednesday</th>
    <td>HTML Tables</td>
    <td>Build a schedule table</td>
  </tr>
</table>
A Simple, High-Value Habit

Adding scope to header cells is a simple habit that meaningfully improves how screen readers present your tables. It is one of the most direct and easy accessibility improvements you can make to tabular data.

Table Captions

A caption is a title for the table. It appears directly above or below the table and is visually and programmatically associated with it. The <caption> element goes immediately after the opening <table> tag, before any rows.

HTML — Table with a Caption
<table>
  <caption>Final Exam Scores — Spring Semester</caption>
  <tr>
    <th scope="col">Student</th>
    <th scope="col">Score</th>
    <th scope="col">Grade</th>
  </tr>
  <tr>
    <td>Amara</td>
    <td>94</td>
    <td>A</td>
  </tr>
</table>

Screen readers announce the caption before reading the table, which helps users understand what they are about to hear. Captions are also valuable for sighted users — a table with a caption is faster to understand than a table with only a heading in the text above it, because the caption is part of the table itself.

Table Sections: <thead>, <tbody>, and <tfoot>

For more complex tables, HTML provides three grouping elements: <thead> groups the header row or rows, <tbody> groups the main data rows, and <tfoot> groups footer rows, often used for totals or summary rows.

HTML — A Sectioned Table with a Footer
<table>
  <caption>Course Fees</caption>
  <thead>
    <tr>
      <th scope="col">Course</th>
      <th scope="col">Credits</th>
      <th scope="col">Fee</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Web Development</td>
      <td>3</td>
      <td>$420</td>
    </tr>
    <tr>
      <td>Programming with Python</td>
      <td>3</td>
      <td>$420</td>
    </tr>
    <tr>
      <td>Computer Science Foundations</td>
      <td>3</td>
      <td>$420</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="2">Total</td>
      <td>$1,260</td>
    </tr>
  </tfoot>
</table>

The colspan="2" attribute in the footer row causes that cell to span two columns, merging the "Course" and "Credits" columns into a single "Total" label. Sectioning a table with <thead>, <tbody>, and <tfoot> improves accessibility, allows CSS to target sections separately, and enables some browsers to repeat the header row on each printed page.

Spanning Cells

Sometimes a single cell should span multiple columns or multiple rows. A merged header, a grouped category, a summary label — these all call for spanning. colspan merges cells horizontally, and rowspan merges cells vertically.

HTML — colspan
<tr>
  <th colspan="2" scope="colgroup">Contact Information</th>
  <th scope="col">Department</th>
</tr>
<tr>
  <th scope="col">Name</th>
  <th scope="col">Email</th>
  <th scope="col">Department</th>
</tr>
HTML — rowspan
<tr>
  <th rowspan="2" scope="rowgroup">Spring</th>
  <td>March</td>
  <td>Registration opens</td>
</tr>
<tr>
  <td>April</td>
  <td>Classes begin</td>
</tr>
A Common Spanning Mistake

Spanning is powerful but can easily produce broken layouts. If you add a colspan="2" to a cell, the total number of columns in that row is reduced by one. The math must stay consistent across all rows. A common beginner mistake is adding a span without adjusting the number of cells in affected rows, which causes columns to misalign.

Sections 9.6 – 9.10
Forms: Collecting Input From Users
Form Basics · Labels and Inputs · Buttons and Menus · Checkboxes and Radio Buttons · Building a Complete Form

What Forms Do

A form is a part of a web page that accepts input from a user and sends that input somewhere — to a server, to a script, or to some other process. Forms are fundamental to interactive web experiences. Without forms, users could not search, register, log in, comment, buy, subscribe, complete surveys, or submit work.

You encounter forms constantly: the search bar on any website, the login screen, the checkout process in an online store, the contact page on a company's site, the admission application for a school, the survey at the end of a purchase.

From the HTML side, a form is a container with input fields. Each field collects one piece of information — a name, an email address, a choice from a set of options, a block of text, a file, a date. The browser manages the appearance and behavior of each field type based on the input type you specify.

The <form> Element

A form begins with the <form> element, which wraps all of the form's fields and controls.

HTML — The Form Element
<form action="submit.html" method="post">
  <!-- form fields go here -->
</form>

Two attributes appear on <form> most often:

AttributePurpose
actionSpecifies where the form data will be sent when the user submits it. In a real website, this is a server-side script that processes the data. For now, it can be a placeholder URL or omitted entirely.
methodSpecifies how the data is sent. The value get adds data to the URL as query parameters, which is visible to the user and suitable for searches. The value post sends data in the background, which is suitable for sensitive information like passwords and form submissions.
What This Chapter Does — and Does Not — Cover

In this chapter, you will not write the server-side code that processes form data. You will learn to build the HTML structure of the form correctly. JavaScript-based form validation and client-side form handling come in Chapter 24.

Labels and Inputs

The Importance of Labels

Before learning any input element, you need to understand labels. Every visible form field needs a <label> element associated with it. This is not optional. It is one of the clearest and most important accessibility rules in web development.

A label tells the user what a field is for. Without a label, a user sees a blank text box and does not know what to type. With a label, the user sees "Email address" or "Your message" beside the field.

But a label does more than display text. When a label is properly associated with its input field:

  • Clicking the label text moves focus to the input field, which significantly increases the clickable area for users with motor difficulties.
  • Screen readers announce the label when the user navigates to the field, so a visually impaired user hears "Email address, required" rather than just a silent blank.
  • Browser auto-fill features can match fields to stored data more reliably.

The primary way to associate a label with an input is with the for attribute on the label and the id attribute on the input. The value of for must exactly match the value of id.

HTML — Explicit Label Association
<label for="email">Email address</label>
<input type="text" id="email" name="email">
The Key Rule

The for on the label must exactly match the id on the input. If the values do not match — even by a single character — the association is broken and the benefits described above are lost. The browser will not warn you. The form will look correct visually while failing silently for assistive technology users.

The <input> Element

The <input> element is a void element — it has no closing tag. It renders a wide variety of controls depending on its type attribute.

The name attribute on every input is important for form submission. When the form is submitted, the browser sends name-value pairs to the server. If an input has no name, its value is not sent.

HTML — name and id Working Together
<label for="username">Username</label>
<input type="text" id="username" name="username">

Common Input Types

Type ValueBehavior
textThe default type. Renders a single-line text field.
emailRenders a text field that validates basic email format on modern browsers. Opens an email-optimized keyboard on mobile.
passwordRenders a text field where characters are hidden — shown as dots or asterisks — to protect sensitive input.
numberRenders a field that accepts numerical input, usually with small increment/decrement arrows. min, max, and step can constrain the range.
telIntended for telephone numbers. Does not enforce a specific format, but opens a numeric keyboard on mobile.
urlRenders a text field that validates URL format. Opens a keyboard with easy access to dots and slashes on mobile.
dateRenders a date picker in supporting browsers, letting users select a year, month, and day.
hiddenRenders nothing visible but sends a value with the form — used for information the user does not need to see, such as a form identifier.
HTML — Several Input Types in Use
<label for="age">Age</label>
<input type="number" id="age" name="age" min="1" max="120">

<label for="phone">Phone number</label>
<input type="tel" id="phone" name="phone">

<label for="startdate">Start date</label>
<input type="date" id="startdate" name="startdate">

<input type="hidden" name="form-version" value="2">

Useful Input Attributes

AttributePurpose
placeholderLight gray hint text shown inside the field before the user types. Not a substitute for a label.
requiredMarks the field as required. The browser will refuse submission if it is empty.
valueSets a default value that appears pre-filled in the field.
disabledMakes the field visible but not interactive. Its value is not submitted.
readonlyAllows the user to see and select the value but not change it. Its value is submitted.
maxlengthLimits the number of characters the user can type.
autocompleteHints to the browser about auto-fill behavior.
A Very Common Beginner Mistake

Using placeholder instead of a label. A placeholder disappears when the user starts typing. If the user pauses midway through filling out the form, they can no longer see what the field asked for. Labels remain visible at all times. Always use both: a visible <label> for the field's purpose, and an optional placeholder for an example value.

Good — Visible Label and Optional Hint
<label for="email">Email address</label>
<input type="email" id="email" name="email" placeholder="[email protected]">
Problematic — Placeholder Only, No Label
<input type="email" id="email" name="email" placeholder="Email address">

Buttons, Text Areas, and Select Menus

Buttons

A button inside a form submits the form by default. The <button> element is the standard way to create a form button.

HTML — A Submit Button
<button type="submit">Send Message</button>

The type="submit" attribute makes the button submit the form. You can also use type="button" to create a button that does not submit the form by default — useful when JavaScript will handle the click.

HTML — A Non-Submitting Button
<button type="button">Preview</button>

There is also type="reset", which clears all fields in the form back to their default values. This is rarely used on modern sites because accidentally clicking reset can frustrate users who have filled in a long form.

The <input type="submit"> element also creates a submit button, but <button> is generally preferred because it can contain HTML content, such as an icon.

HTML — Two Ways to Create a Submit Button
<!-- Both produce a submit button -->
<button type="submit">Send</button>
<input type="submit" value="Send">
Write Descriptive Button Text

"Submit" is adequate but vague. "Send Message," "Create Account," "Apply Now," or "Download Report" tell the user exactly what will happen when they click. This matters for all users, but especially for screen reader users who may navigate directly to buttons.

Text Areas

A text area is a multi-line text input. Use it when you expect longer text: a message, a comment, a description, a biography.

The <textarea> element has an opening and closing tag. Any content between them becomes the default value. The rows and cols attributes suggest the initial display size, though CSS is more reliable for controlling dimensions.

HTML — Text Area
<label for="bio">Short biography</label>
<textarea
  id="bio"
  name="bio"
  rows="4"
  placeholder="Tell us a little about yourself."
  maxlength="500"></textarea>

Unlike <input>, <textarea> does not have a type attribute — it is always a multi-line text field. It does accept required, placeholder, maxlength, disabled, and readonly attributes.

Select Menus

A select menu presents a list of options in a dropdown. The <select> element wraps <option> elements, each representing one choice.

HTML — Select Menu
<label for="country">Country</label>
<select id="country" name="country">
  <option value="">— Select your country —</option>
  <option value="us">United States</option>
  <option value="ca">Canada</option>
  <option value="mx">Mexico</option>
  <option value="gb">United Kingdom</option>
</select>

Each <option> has a value attribute — this is what gets submitted with the form. The text inside the <option> tags is what the user sees. These can be different: the user sees "United States," but the form submits the value "us".

The first option in the example above has an empty value and serves as a prompt. Without a selected option, users might not notice they need to choose one. Adding a prompt option makes the field's purpose clear.

The selected attribute marks an option as the pre-selected choice:

HTML — A Pre-Selected Option
<option value="ca" selected>Canada</option>

For long lists, <optgroup> groups related options under a label:

HTML — Grouped Options
<select id="timezone" name="timezone">
  <optgroup label="North America">
    <option value="est">Eastern Time (UTC-5)</option>
    <option value="cst">Central Time (UTC-6)</option>
    <option value="pst">Pacific Time (UTC-8)</option>
  </optgroup>
  <optgroup label="Europe">
    <option value="gmt">Greenwich Mean Time (UTC+0)</option>
    <option value="cet">Central European Time (UTC+1)</option>
  </optgroup>
</select>

Adding the multiple attribute allows users to select more than one option at once, which displays the list as a scrollable box rather than a dropdown.

Checkboxes and Radio Buttons

Checkboxes and radio buttons are input elements for selecting options. They work similarly in HTML but communicate different kinds of choices to the user.

Checkboxes

A checkbox represents a single on/off choice, or one item from a group of independent options where any number can be selected.

HTML — A Single Checkbox (Implicit Label)
<label>
  <input type="checkbox" name="newsletter" value="yes">
  Subscribe to our newsletter
</label>

Notice the structure here: the <input> is placed inside the <label> element. This is called an implicit label association — because the input is inside the label, they are automatically associated without needing matching id and for attributes. Either approach is valid. Many developers prefer the explicit approach because it is clearer when reading the code, but both work correctly.

HTML — Explicit Association
<input type="checkbox" id="terms" name="terms" value="agreed">
<label for="terms">I agree to the terms and conditions</label>

When a form has a group of checkboxes, each checkbox can have the same name but should have a distinct value. Only checked boxes submit their values.

HTML — A Group of Checkboxes
<fieldset>
  <legend>Which topics interest you?</legend>

  <label>
    <input type="checkbox" name="topics" value="html">
    HTML
  </label>

  <label>
    <input type="checkbox" name="topics" value="css">
    CSS
  </label>

  <label>
    <input type="checkbox" name="topics" value="javascript">
    JavaScript
  </label>

  <label>
    <input type="checkbox" name="topics" value="accessibility">
    Accessibility
  </label>
</fieldset>
Fieldset and Legend

The <fieldset> element groups related form controls. The <legend> element provides a caption for the group. A screen reader reads the legend before reading each option inside the fieldset, so a user hears "Which topics interest you? HTML checkbox, unchecked. CSS checkbox, unchecked." This context is essential when the group label is not otherwise connected to the individual controls. Always use <fieldset> and <legend> when grouping related checkboxes or radio buttons.

Radio Buttons

Radio buttons represent a single choice from a set of mutually exclusive options. When the user selects one radio button in a group, any previously selected radio button in the same group is automatically deselected — like the preset buttons on an old car radio, which is where the name comes from.

Radio buttons in the same group must share the same name attribute. Each button must have a distinct value.

HTML — A Group of Radio Buttons
<fieldset>
  <legend>Preferred contact method</legend>

  <label>
    <input type="radio" name="contact" value="email">
    Email
  </label>

  <label>
    <input type="radio" name="contact" value="phone">
    Phone
  </label>

  <label>
    <input type="radio" name="contact" value="mail">
    Postal mail
  </label>
</fieldset>

Only one option in this group can be selected at a time. When the form is submitted, only the selected option's name and value are sent. You can add checked to pre-select one option:

HTML — Pre-Selected Radio Button
<input type="radio" name="contact" value="email" checked>

Choosing Between Checkboxes and Radio Buttons

The difference is in how many options can be selected simultaneously. Use checkboxes when any number of options can be selected, including zero or all. Use radio buttons when exactly one option must be selected from a group. A practical test: if the user could logically choose more than one answer, use checkboxes. If the user must commit to exactly one answer from the list, use radio buttons.

QuestionInput Type
Which languages do you know?Checkboxes
What is your highest level of education?Radio buttons
Select all that apply:Checkboxes
Choose one:Radio buttons
Which newsletters would you like?Checkboxes
What is your preferred payment method?Radio buttons

Building an Accessible Contact Form

You now have all the building blocks for a complete form. This section walks through building a realistic contact form from planning to finished code, focusing on accessible structure throughout.

Planning the Form

A contact form typically collects the sender's name, the sender's email address, the subject of the message, the message itself, and a submit button. Before writing any code, it helps to list the fields, their types, whether they are required, and what their labels will say.

FieldInput TypeRequired?Label Text
Full nametextYesYour name
EmailemailYesEmail address
SubjectselectNoSubject
MessagetextareaYesYour message
Submitbutton—Send Message

The Finished Form

HTML — Complete 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 — Student Learning Site</title>
</head>
<body>

  <main>
    <h1>Contact Us</h1>
    <p>Fill in the form below and we will get back to you within two business days.</p>

    <form action="#" method="post" novalidate>

      <div>
        <label for="fullname">Your name <span aria-hidden="true">*</span></label>
        <input
          type="text"
          id="fullname"
          name="fullname"
          autocomplete="name"
          required>
      </div>

      <div>
        <label for="email">Email address <span aria-hidden="true">*</span></label>
        <input
          type="email"
          id="email"
          name="email"
          autocomplete="email"
          placeholder="[email protected]"
          required>
      </div>

      <div>
        <label for="subject">Subject</label>
        <select id="subject" name="subject">
          <option value="">— Choose a subject —</option>
          <option value="general">General question</option>
          <option value="lessons">Questions about lessons</option>
          <option value="resources">Questions about resources</option>
          <option value="feedback">Feedback or suggestions</option>
          <option value="other">Other</option>
        </select>
      </div>

      <div>
        <label for="message">Your message <span aria-hidden="true">*</span></label>
        <textarea
          id="message"
          name="message"
          rows="6"
          required></textarea>
      </div>

      <p>Fields marked <span aria-hidden="true">*</span><span class="sr-only">with an asterisk</span> are required.</p>

      <div>
        <button type="submit">Send Message</button>
      </div>

    </form>
  </main>

</body>
</html>

Walking Through the Form

Detail 1
The <form> Element
Uses action="#" as a placeholder ("#" means "this page," so nothing is actually submitted). The novalidate attribute tells the browser not to apply its built-in validation messages — handled with JavaScript in Chapter 24.
Detail 2
Field Group Containers
Each label-input pair is wrapped in a <div>, giving a structural container that makes CSS styling straightforward — each group can be targeted as a unit.
Detail 3
The Required Asterisk
<span aria-hidden="true"> hides the visual asterisk from screen readers, which would otherwise read it as "asterisk" or "star." A separate sr-only note explains required fields in words for screen reader users.
Detail 4
Autocomplete Attributes
autocomplete="name" and autocomplete="email" help browsers fill in known information for the user — a real usability improvement, especially on mobile.
Detail 5
The required Attribute
Tells the browser these three fields cannot be empty on submission. JavaScript validation in Chapter 24 builds on top of this baseline.
Detail 6
The Submit Button
Uses descriptive text — "Send Message" — rather than a vague label like "Submit" or "Go."

What Accessible Forms Sound Like in Practice

When a screen reader user navigates this form, they hear something like the sequence below:

Screen Reader Walkthrough
What the user hears, step by step
  • Heading"Contact Us, heading level one."
  • Intro"Fill in the form below..."
  • Name field"Your name, required, edit text" — because the label is associated and required is present.
  • Email field"Email address, required, edit text."
  • Subject field"Subject, combo box" — the select menu.
  • Message field"Your message, required, text area."
  • Required note"Fields marked with an asterisk are required" — because the sr-only text is announced.
  • Button"Send Message, button."
The Principle Behind All of It

Each piece of that experience depends on the HTML being correctly structured. Remove the labels and the user hears only blank edit fields with no context. Remove the required attributes and the user does not know which fields are mandatory. Remove the descriptive button text and the user hears only "button." Good form structure is not extra work layered on top of a finished form. It is how the form is built from the start.

Chapter Summary

This chapter introduced three major categories of HTML content structure: lists, tables, and forms. The running principle across all three is the same: HTML communicates structure and meaning, not just appearance. A list is not just indented text with bullets. A table is not just a grid drawn on a page. A form is not just a collection of boxes. Each is a semantic structure that the browser, search engines, and assistive technologies can read and use.

Key Terms

unordered list
An HTML list where the order of items does not carry meaning, created with <ul>. Items display with bullet points by default.
ordered list
An HTML list where the order of items is meaningful, created with <ol>. Items display with numbers by default.
list item
The element <li>, used inside <ul> or <ol> to mark each item in a list.
description list
An HTML list structure for term-definition pairs, created with <dl>, with <dt> for terms and <dd> for definitions.
table
An HTML structure for presenting data in rows and columns, created with <table>.
table row
A row inside a table, created with <tr>.
table header cell
A cell containing a column or row label, created with <th>. Displayed as bold and centered by default.
table data cell
A regular data cell inside a table row, created with <td>.
scope attribute
An attribute on <th> that identifies whether the header applies to a column (scope="col") or a row (scope="row").
caption
A title for a table, created with <caption>, placed immediately after the opening <table> tag.
colspan
An attribute that causes a cell to span multiple columns.
rowspan
An attribute that causes a cell to span multiple rows.
form
An HTML container for input fields that can collect and submit user data, created with <form>.
label
The <label> element, which provides a visible description for a form field and associates with it using for and id.
input
The <input> void element, which creates a variety of form controls depending on its type attribute.
textarea
The <textarea> element, which creates a multi-line text input field.
select
The <select> element, which creates a dropdown menu of <option> elements.
checkbox
An input with type="checkbox" that allows independent on/off selections.
radio button
An input with type="radio" that allows exactly one selection from a named group.
fieldset
The <fieldset> element, which groups related form controls.
legend
The <legend> element, which provides a caption for a <fieldset>.
required
An attribute that marks a form field as mandatory for submission.
placeholder
An attribute that displays hint text inside an input field before the user types. Not a substitute for a label.

Code Reading

Read each code block carefully. For each one, describe what the browser would display and identify any problems.

Exercise 1
<ul>
  <li>Planning</li>
  <li>Research</li>
  <li>Writing</li>
  <li>Editing</li>
  <li>Publishing</li>
</ul>
What type of list is this? When would an ordered list be more appropriate for this content?
Exercise 2
<ol>
  <li>Preheat oven to 375 degrees.</li>
  <li>Mix dry ingredients in a large bowl.</li>
  <li>Add wet ingredients and stir until combined.</li>
  <li>Pour into a greased baking dish.</li>
  <li>Bake for 30 minutes.</li>
</ol>
Why is an ordered list more appropriate here than an unordered list?
Exercise 3
<ul>
  <li>Vegetables
    <ul>
      <li>Carrots</li>
      <li>Broccoli</li>
      <li>Spinach</li>
    </ul>
  </li>
  <li>Fruits
    <ul>
      <li>Apples</li>
      <li>Bananas</li>
    </ul>
  </li>
  <li>Grains</li>
</ul>
Describe the structure. How many items are in the outer list? How many items are in each inner list?
Exercise 4
<table>
  <tr>
    <th>Day</th>
    <th>High Temperature</th>
    <th>Low Temperature</th>
  </tr>
  <tr>
    <td>Monday</td>
    <td>72°F</td>
    <td>58°F</td>
  </tr>
  <tr>
    <td>Tuesday</td>
    <td>68°F</td>
    <td>55°F</td>
  </tr>
</table>
What is missing from the header cells that would improve accessibility? How many columns does this table have? How many data rows?
Exercise 5
<form action="/contact" method="post">
  <input type="text" name="username" placeholder="Enter your name">
  <input type="email" name="email" placeholder="Enter your email">
  <button type="submit">Submit</button>
</form>
This form has a serious accessibility problem. Identify it and explain how to fix it.
Exercise 6
<fieldset>
  <legend>Preferred learning format</legend>

  <label>
    <input type="radio" name="format" value="video">
    Video lectures
  </label>

  <label>
    <input type="radio" name="format" value="text">
    Reading materials
  </label>

  <label>
    <input type="radio" name="format" value="interactive">
    Interactive exercises
  </label>
</fieldset>
Why are these inputs inside a <fieldset>? What attribute makes these radio buttons part of the same group? Can the user select more than one option?
PracticeList and Table Practice
Task 1 — Unordered List

Write an unordered list of five tools a web developer uses. Use appropriate HTML structure with <ul> and <li>.

Task 2 — Ordered List with Nesting

Write an ordered list of three major steps for starting a web project. Add an unordered sub-list of two to three items inside at least one step.

Task 3 — Description List

Write a description list with four terms and their definitions. Choose a topic from this chapter: HTML lists, HTML tables, HTML forms, or any four input types.

Task 4 — Data Table

Write a table that shows a simple class schedule with four rows of data. Include a caption, header cells with scope="col", and wrap the rows in <thead> and <tbody> sections. The table should have these columns: Day, Time, Subject, Room.

Task 5 — Table with a Footer

Extend your schedule table from Task 4 by adding a <tfoot> row that spans all columns and contains a note such as "All rooms are in Building A." Use colspan to span the note across all four columns.

PracticeForm Structure Practice
Task 6 — Basic Contact Form Fields

Write the HTML for three labeled input fields: a text field for a full name, an email field for an email address, and a text field for a phone number. Each field must have a visible <label> with a matching for and id. Each field must have a name attribute.

Task 7 — Select Menu

Write a labeled <select> menu that asks users to choose their time zone from a list of at least six options. Group the options using two <optgroup> elements.

Task 8 — Checkboxes with Fieldset

Write a <fieldset> with a <legend> and four checkboxes representing four types of notifications a user might want to receive (for example: email digest, new lesson alerts, event reminders, weekly summary).

Task 9 — Radio Buttons with Fieldset

Write a <fieldset> with a <legend> and four radio buttons for a single-choice question. All radio buttons must share the same name and have distinct value attributes.

Task 10 — Textarea

Write a labeled <textarea> for a "Short biography" field. The textarea should have at least four rows and include a placeholder hint. It should be marked as required.

Label Accessibility Check

Review the following form code and answer the questions.

HTML — Form for Review
<form>
  <div>
    <p>Name:</p>
    <input type="text" name="name" placeholder="Your name">
  </div>
  <div>
    <label>Email</label>
    <input type="email" name="email">
  </div>
  <div>
    <label for="msg">Message</label>
    <input type="text" id="message" name="msg">
  </div>
  <div>
    <input type="checkbox" name="agree" value="yes">
    I agree to the terms.
  </div>
  <button>Go</button>
</form>
  1. Question 1: The first field uses a <p> element as its label. Why does this fail accessibility requirements?
  2. Question 2: The second field has a <label> element, but the association is incomplete. What is missing?
  3. Question 3: The third field has a for attribute on the label and an id on the input. Is the association correct? Look carefully.
  4. Question 4: The fourth field is a checkbox without a visible label element. Write a corrected version of this checkbox that properly associates a label with the input.
  5. Question 5: The submit button reads "Go." Why is this a usability problem? Write a more descriptive replacement.

Debugging Practice

Each code block below contains one or more errors. Identify each error and write a corrected version.

Debug 1
<ol>
  <ul>
    <li>First step</li>
    <li>Second step</li>
  </ul>
  <li>Third step</li>
</ol>
Debug 2
<table>
  <tr>
    <th>Name</th>
    <th>Score</th>
  </tr>
  <tr>
    <td>Priya</td>
    <td>88</td>
    <td>Passed</td>
  </tr>
</table>
Debug 3
<label for="phone">Phone number</label>
<input type="tel" id="telephone" name="phone">
Debug 4
<fieldset>
  <input type="radio" name="size" value="small"> Small
  <input type="radio" name="size" value="medium"> Medium
  <input type="radio" name="size" value="large"> Large
</fieldset>
Debug 5 — Find Two Issues
<label for="country">Country</label>
<select name="country">
  <option>United States</option>
  <option>Canada</option>
  <option>Mexico</option>
</select>

Common Errors

Using <br> Tags to Separate List Items

Wrong — Breaks Inside a Fake List
Apples<br>
Oranges<br>
Bananas<br>
Correct — An Actual List
<ul>
  <li>Apples</li>
  <li>Oranges</li>
  <li>Bananas</li>
</ul>

Nesting a List Directly Inside Another List

Wrong — <ul> Directly Inside <ol>
<ol>
  <li>First</li>
  <ul>
    <li>Sub-item</li>
  </ul>
  <li>Second</li>
</ol>
Correct — <ul> Inside an <li>
<ol>
  <li>First
    <ul>
      <li>Sub-item</li>
    </ul>
  </li>
  <li>Second</li>
</ol>

Using Tables for Layout

Wrong — Table Used to Control Column Layout
<table>
  <tr>
    <td><nav>Navigation links here</nav></td>
    <td><main>Page content here</main></td>
  </tr>
</table>
Correct — CSS for Layout, Table for Actual Data Only
<nav>Navigation links here</nav>
<main>Page content here</main>

Tables are for data. CSS handles layout.

Missing or Mismatched for and id on Labels

Wrong — for and id Don't Match
<label for="user-email">Email</label>
<input type="email" id="email" name="email">
Correct — for and id Match Exactly
<label for="email">Email</label>
<input type="email" id="email" name="email">

Using Placeholder as a Label Substitute

Wrong — No Label, Placeholder Only
<input type="text" name="name" placeholder="Your name">
Correct — Visible Label Plus Optional Placeholder Hint
<label for="name">Your name</label>
<input type="text" id="name" name="name" placeholder="e.g. Sam Rivera">

Checkboxes or Radio Buttons Without Fieldset and Legend

Wrong — No Grouping Context for Screen Readers
<input type="radio" name="size" value="s"> Small
<input type="radio" name="size" value="m"> Medium
<input type="radio" name="size" value="l"> Large
Correct — Fieldset and Legend Provide Group Context
<fieldset>
  <legend>Choose a size</legend>
  <label><input type="radio" name="size" value="s"> Small</label>
  <label><input type="radio" name="size" value="m"> Medium</label>
  <label><input type="radio" name="size" value="l"> Large</label>
</fieldset>

Options in a Select Menu Without Values

Wrong — No Value Attributes
<select name="country">
  <option>United States</option>
  <option>Canada</option>
</select>
Correct — Each Option Has a Value
<select id="country" name="country">
  <option value="us">United States</option>
  <option value="ca">Canada</option>
</select>

Mixed Review

These questions draw on material from Chapters 5 through 9.

  1. What is the difference between a structural element and a semantic element? Give one example of an element that is both.
  2. You are building a recipe page. Which list type would you use for the ingredients? Which would you use for the cooking steps? Explain why each choice fits.
  3. A classmate says, "I don't need labels on my form. I used placeholder text so users can see what to type." Write a response explaining at least two reasons why placeholder text is not a sufficient replacement for visible labels.
  4. You have a table with the following columns: Country, Capital, Population, Area. Write the HTML for the header row using proper scope attributes.
  5. What is the difference between a checkbox and a radio button? Give an example of a real form question that should use a checkbox and a real form question that should use a radio button.
  6. A navigation menu is built using an unordered list of anchor elements. Why is an unordered list more semantically appropriate than an ordered list for a navigation menu?
  7. You are building a table that shows monthly rainfall for a city over one year. The first column contains month names and the second column contains rainfall in millimeters. Should the month names use <td> or <th>? What scope value should they use?
  8. What does the name attribute do on a form input? What happens if you omit it?
Mini-Project: Accessible Contact Form Page
Build a complete, accessible contact form page for the Student Learning Site
HTML Structure
  • Valid HTML5 document with <!DOCTYPE html>, <html lang="en">, <head>, and <body>.
  • Appropriate <meta charset> and <meta name="viewport">.
  • A <title> that reads: Contact — Student Learning Site.
  • A <main> landmark containing the form.
  • An <h1> heading above the form.
  • A short introductory paragraph before the form.
Form Fields
  • All fields have visible <label> elements with matching for and id attributes.
  • A text input for full name (required).
  • An email input for email address (required).
  • A select menu for "How did you hear about us?" with at least five options, including a blank prompt option.
  • A <fieldset> with a <legend> and at least three checkboxes for topics the user is interested in.
  • A textarea for a message (required, at least 6 rows).
  • A submit button with descriptive text.
Required Fields
  • All required fields are marked using the required attribute.
  • A note visible on the page explains which fields are required.
Accessibility
  • <fieldset> and <legend> are used around the checkbox group.
  • Placeholder text is never used as the sole label for any field.
  • The submit button has descriptive text.
  • autocomplete attributes are used on the name and email fields.
Stretch Goal
  • Add a second <fieldset> below the checkbox group. Inside it, use radio buttons to ask: "How would you prefer to be contacted?" with options for email, phone, and no preference. Apply proper name, value, <label>, <fieldset>, and <legend> structure.
ReviewReview Questions
  1. Name the three types of HTML lists. For each one, give the element name and a real-world example of content that fits it.
  2. What is the rule for nesting lists? What is the correct structure for placing a sub-list inside a parent list item?
  3. Explain the difference between <th> and <td>. When should you use each?
  4. What does scope="col" mean on a <th> element? What does scope="row" mean?
  5. What does the <caption> element do? Where does it go in the table structure?
  6. Explain the purpose of <thead>, <tbody>, and <tfoot>. Are these required for a valid table?
  7. What does colspan="3" do? What does rowspan="2" do? Give an example of a table where each would be appropriate.
  8. Why must every visible form field have a <label> element? Name two specific benefits that a properly associated label provides.
  9. What is the difference between the for attribute on a label and the id attribute on an input? How must they be related?
  10. What is the name attribute on a form input, and why is it required for form submission?
  11. List five different values for the type attribute on an <input> element. For each one, describe what it produces and when you would use it.
  12. What is the difference between a <textarea> and an <input type="text">? When would you choose one over the other?
  13. What does the required attribute do on a form input?
  14. When should you use checkboxes versus radio buttons? Give one example of each.
  15. Why should related checkboxes and radio buttons be grouped inside a <fieldset> with a <legend>?
Chapter 9 Checklist
Use this to confirm your understanding before moving to Chapter 10
Lists
  • I can explain why HTML lists carry more meaning than manually typed dashes or numbers.
  • I can build unordered, ordered, and description lists with correct elements.
  • I can correctly nest a list inside a list item.
Tables
  • I can build a table using <table>, <tr>, <th>, and <td>.
  • I can apply the scope attribute correctly to column and row headers.
  • I can add a caption and section a table with <thead>, <tbody>, and <tfoot>.
  • I can use colspan and rowspan to merge cells without breaking row alignment.
  • I understand why tables should never be used for page layout.
Forms
  • I can explain what the action and method attributes do on a <form>.
  • I can correctly associate a label with an input using for and id.
  • I can choose the appropriate input type for a given kind of data.
  • I can build a select menu, a textarea, checkboxes, and radio buttons.
  • I can group related checkboxes or radio buttons using <fieldset> and <legend>.
  • I can build a complete, accessible contact form from a written plan.
Preview — Chapter 10
Metadata, SEO Basics, and Document Quality

Chapter 9 completed the major visible content structures of HTML: lists, tables, and forms. Chapter 10 moves from visible content to the hidden layer of HTML documents: metadata. You will learn how the <head> section communicates with browsers, search engines, and sharing platforms. Topics include character encoding, the viewport meta tag, page descriptions, favicons, and a first look at how HTML structure affects how a page appears in search results. Chapter 10 completes the HTML part of the book and sets the stage for moving into CSS in Part III.

MGU Library Connection
  • Web Development: HTML, CSS, and JavaScript — Appendix B: HTML Reference
  • Web Development: HTML, CSS, and JavaScript — Appendix C: Semantic HTML and Accessibility Reference
  • Web Development: HTML, CSS, and JavaScript — Appendix H: Forms and User Feedback Reference
  • Companion resource: HTML Form Guide
  • Companion resource: Accessibility Checklist
  • Next chapter: Chapter 10 — Metadata, SEO Basics, and Document Quality