Web Development · Lesson 5

HTML Tables

Build HTML tables with caption, row, header, and data cells, style them with CSS3, span cells, and reserve tables for tabular data.

  • html-tables
  • css3
  • colspan-rowspan
  • page-structure
  • responsive-tables

Lesson purpose

Lesson 5 teaches students to present information that naturally belongs in rows and columns — staff directories, price lists, schedules, grades — as an HTML table styled with CSS3. Students build table structure with five elements, format it with CSS3 properties instead of deprecated HTML attributes, merge cells with colspan and rowspan, and learn the judgment call at the center of the lesson: a table is for tabular data, never for laying out a page. Page layout belongs to the HTML5 structure elements students met earlier.

Quick opener: ask students where they have seen a table this week (class schedule, bank statement, sports standings). Each one compares data across rows and columns — exactly what a table is for.

Learning objectives

By the end of the lesson, students should be able to:

  • CIW 2.1.5: Design and format HTML tables to present information in an organized way.
  • Build valid table structure with <table>, <caption>, <tr>, <th>, and <td>.
  • Style borders, spacing, size, color, and alignment with CSS3 rather than deprecated HTML attributes.
  • Span cells across columns and rows with colspan and rowspan.
  • Decide when a table belongs on a page and when HTML5 structure elements should be used instead.
  • Explain how a responsive (Bootstrap) table keeps wide data usable on small screens.

1. Why tables instead of <pre>

Tables have been part of HTML since HTML 2.0 and have expanded ever since. Students already know the <pre> tag can line up text in columns, but <pre> is extremely limited: it only preserves spacing in monospaced text. A real table allows images, alignment, color, borders, spacing, and many other customizations, and — just as important — it tells browsers and screen readers that the content is a grid of related data.

Check for understanding: “If <pre> can line text up in columns, what does a table add?” (Styling control, semantic meaning, and accessibility.)

2. The five table elements

Every table is built from the same small set of paired tags. None are self-closing.

Element Tag Required? What it does
Table <table>...</table> Required Creates the table; contains every other table element.
Table caption <caption>...</caption> Optional Adds a title, which appears above the table by default.
Table row <tr>...</tr> Required Holds all the cells for one row.
Table header <th>...</th> Optional Labels a column or row; bold and centered by default.
Table data <td>...</td> Required (unless <th> is used) Holds the actual values; left-aligned by default.

Talking points for each element:

  • <table> is the container. Every other table tag lives inside it.
  • <caption> is the table’s title. It is optional but strongly recommended because it tells readers — and screen-reader users — what the table is about. It must be the first thing inside <table>.
  • <tr> creates one row. Cells always go inside a row; a cell is never placed directly inside <table>.
  • <th> vs. <td> is more than appearance. <th> tells the browser and assistive technology “this cell is a label”; <td> holds the data being labeled. Typically header cells run across the top row or down the left column.

Figure 5-1 in the book labels the other visible parts of a table that CSS controls: the table border, the cells, the padding inside each cell, and the border spacing between cells.

Quick check: “Which tags could you leave out and still have a working table?” (<caption> and <th>.)

The lesson’s HTML Tables video walks the same build order students will use in Lab 5-1: add the <table> element, add a <caption>, decide the column headings, add a header row of <th> cells, then add a <tr> of <td> cells for each record. It then previews the CSS used to format a table (border, padding, height, width, background color, text alignment, vertical alignment) and closes by contrasting tables with the HTML5 structure elements used for page layout.

The example table

<table>
  <caption>Table Elements</caption>
  <tr>
    <th>Price</th>
    <th>Quantity</th>
  </tr>
  <tr>
    <td>13.95</td>
    <td>72</td>
  </tr>
</table>
table,
td,
th {
  border: 1px solid gray;
}

td,
th {
  padding: 15px;
}

td {
  text-align: center;
}

Walk through it line by line:

  1. <caption>Table Elements</caption> — the title, first inside <table>, rendered above the grid.
  2. First <tr> — the header row. Two <th> cells, Price and Quantity, label the columns and appear bold and centered.
  3. Second <tr> — a data row. Two <td> cells hold the values. Each record gets its own <tr>, and each row should have as many cells as there are columns.
  4. table, td, th { border: ... } — one grouped selector draws a gray line around the table and around every cell.
  5. td, th { padding: 15px; } — adds space inside every cell.
  6. td { text-align: center; } — centers the data values; <th> is already centered by default.

Point out the indentation: each nesting level is indented so it is obvious which tags are inside which. The browser does not care, but people reading and debugging the code do.

Common mistake: forgetting a closing </tr>. The next row then ends up inside the previous one and the table renders incorrectly. The validator will catch it.

3. Style tables with CSS3, not HTML attributes

Older HTML used a border attribute on the table tag (<table border="1">): "1" showed a border, "0" or no attribute showed none. By default, tables have no visible border. The border attribute and similar presentational attributes are deprecated in HTML5 and will not pass validation, so all table styling goes in CSS.

Tech note from the book: do not confuse the CSS border property with the old HTML border attribute. The property defines the border’s width, line style, and color.

The same CSS properties can be applied to any table element — table, tr, th, or td. The selector decides where the style lands.

Property What it controls Values
border Border width, line style, and color e.g., 1px solid gray
border-collapse Merges adjacent cell borders into one line collapse
border-spacing Gap between adjacent cell borders pixels
padding Space between cell content and its border pixels
width How far the table or cell extends horizontally pixels or percent
background-color Fill color behind table elements color name or hex code
text-align Horizontal alignment left, center, right, justify
vertical-align Vertical alignment top, middle, bottom

Have students predict each change before you show it.

Borders

th, td { border: 1px solid black; }
table { border-collapse: collapse; }
  • border — the three values are width, style, and color. Applied to th, td, every cell gets its own box, with a small gap between boxes because browsers keep cell borders separate by default. If border is applied only to table, you get one line around the outside and no lines between cells.
  • border-collapse: collapse — merges neighboring borders into a single shared line, producing the clean grid most people expect. It goes on the table, because it controls how the cells fit together.

Spacing

table { border-spacing: 6px; }
td { padding: 15px; }

These are the pair students mix up most:

  • border-spacing adds space between cells. It only works when borders are separate; with border-collapse: collapse there is no gap to size. It goes on the table.
  • padding adds space inside a cell, between the text and the border. It makes tables much easier to read. Use th, td as the selector to pad header cells too.

Memory aid: text touching the cell border → padding. Cells jammed against each other → border-spacing.

Width and background color

table { width: 90%; }
th { background-color: #CBB677; }
  • width — by default a table is only as wide as its content. Width can be pixels (fixed) or a percentage (a share of the containing space). Prefer percentages: a 900px table may not fit on a phone, but a 90% table always fits.
  • background-color — accepts a color name (green) or hex code (#00FF00). Here only the header cells change because the selector is th. td colors data cells, tr colors whole rows, and table colors everything. Keep strong contrast between text and background so the table stays readable.

Alignment

td { text-align: right; }
td { vertical-align: top; }
  • text-align is left-to-right position. Right-aligning numbers lines up decimal points like a spreadsheet, which makes prices easier to compare. In a real page, right-align only the number column with a class (for example, td.price).
  • vertical-align is top-to-bottom position; the default is middle. It matters only when a row is taller than its content — for example, when one cell holds a long description and the others hold a single word.

4. Default alignment and consistency

With no CSS applied, browsers render:

Cell type Horizontal Vertical Weight
<th> header cell center middle bold
<td> data cell left middle normal

Both types are vertically centered by default; the difference is horizontal position and boldness.

Consistency rule: align content consistently within each column. If each row uses a different horizontal alignment, the table looks unplanned. Numbers and prices are commonly right-aligned.

Troubleshooting connection: if a “header” row appears left-aligned and not bold, the cells were probably written as <td> instead of <th>. Fix the markup — no CSS is needed.

Aligning one cell or a whole row

When cell content wraps onto several lines, a neighboring short cell stays vertically centered. The book shows two ways to move “William Gates” to the top of its cell:

/* Option 1: the whole row */
tr {
  vertical-align: top;
}

/* Option 2: only cells with the class */
td.valign {
  vertical-align: top;
}
<tr>
  <td class="valign">William Gates</td>
  <td>Known to most as "Bill Gates." ...</td>
</tr>
  • A rule on tr affects every cell in the row.
  • A class such as valign affects only the cells that carry it and can be reused on any <td>.
  • In the book’s example, both produce the same result because the long description cell is already full from top to bottom.

5. Height, width, and centering the table

The book demonstrates sizing with the same two-row Table Examples biography table (Bill Gates and Linus Torvalds), changing one setting at a time:

  • Table height (Figure 5-8) — setting height: 500px on the CSS table rule makes the table taller and distributes the extra height evenly across all rows. Extra height can waste page space, so use it only when it improves readability.
  • Cell height (Figure 5-9) — the table height is removed and a 75px height class is applied only to the cell containing Description. The figure caption names the rule td.height { height: 75px; }, but Description is a header cell, so in students’ own code the selector must match the element that carries the class (th.height, or simply .height). That makes the entire header row 75px tall, because every cell in a row shares a height. If several cells in a row set different heights, the largest value wins; the order of the rules does not matter.
  • Column width (Figure 5-10) — all heights are removed and th.width { width: 50%; } is applied to the first <th> (Individual). Setting a header cell’s width sizes its whole column.
  • Table width and centering (Figure 5-11) — the table’s width is changed to 70% and the table is centered on the page.
  • Percent sizing — the book calls percentages the better practice so tables render properly on every device, including small screens.
  • Centering the table — create a class with automatic side margins and apply it to the table. The browser splits the leftover space equally on both sides — the same technique used to center an image.
table.center {
  margin-left: auto;
  margin-right: auto;
}
<table class="center">

Common mistake: using text-align: center to center the table on the page. text-align moves content inside cells; it does not move the table itself.

6. Spanning columns and rows

colspan and rowspan are HTML attributes (not CSS) that let one cell stretch across more than one column or row. Both work on <th> and <td>, and a table can use both. On a <th>, the value is the number of header positions the cell covers; on a <td>, it is the number of standard data cells it covers.

The Column and Row Spanning video reviews both examples below; play it before the code walkthrough.

colspan

<tr>
  <th colspan="2">
    Brief Biographies of Bill Gates and Linus Torvalds
  </th>
</tr>
  • colspan="2" stretches this header across two columns.
  • The row previously had two <th> cells; because one cell now fills both spaces, the other header cell is removed.
  • Typical use: a title row above several columns.

rowspan

<tr>
  <th rowspan="3">
    Bill Gates and Linus Torvalds
  </th>
  <th>
    Biographies
  </th>
</tr>
  • rowspan="3" stretches the cell down across three rows: the row it starts in (beside the Biographies header) plus the two biography rows below it.
  • The rows below have one fewer cell, because the spanning cell already occupies that space.
  • Watch the wording: the book’s text says the cell “spans two rows,” meaning the two data rows, while the code counts all three rows the cell occupies. The rowspan value is always the total number of rows, including the starting row. Ask students to count the rows in Figure 5-13 to see why the value is 3.

The most common mistake: adding colspan or rowspan without removing the cell it replaces. The browser shows no error — the table simply grows an extra cell sticking out of the grid. Have students count columns: a title over a three-column table is colspan="3".

7. Tables vs. HTML5 page structure

For years, developers used invisible tables to lay out entire Web pages, largely because browser support for CSS was weak. In HTML5, the W3C recommends against using tables for page structure. Use the HTML5 structure elements instead:

  • <header> — top of the page, like a word-processing header (logo, site name).
  • <nav> — navigation links to other pages of the site.
  • <section> — a section of a document, such as an introduction, content, or contact information.
  • <article> — site content such as services, articles, blog posts, images, and video.
  • <aside> — content aside from the main article, such as ads, news feeds, or highlighted links.
  • <footer> — bottom of the page (copyright, contact information).

These elements are understood natively by any HTML5 browser on phones, tablets, and laptops, replacing the old “jack of all trades” <div> approach.

Why layout tables cause problems:

  • Pages are hard to update and debug.
  • Screen readers announce the page as rows and columns of data, which confuses users.
  • Layout tables do not adapt well to different screen sizes.
  • A search engine may rank a page lower when tables are used for structure.

Book tech tip: use tables tastefully and sparingly — even legitimate data tables cause problems when overused on a page.

Instructor note: as tables become more complex, students will see why GUI HTML editors are popular. Hand-coding them is still essential so students can read, fix, and customize tables those editors generate.

8. Bootstrap responsive tables

Bootstrap is a free, open-source, front-end framework of HTML and CSS design templates. It is mobile-first and one of the most popular projects on GitHub. Bootstrap tables use light padding and horizontal dividers.

A responsive design site works properly and seamlessly on every screen size and resolution. Bootstrap’s responsive table keeps a wide table from breaking a small-screen layout:

<div class="table-responsive">
  <table class="table">
    ...
  </table>
</div>
  • The .table-responsive class goes on a wrapper <div>, not on the <table>.
  • When the table is wider than the screen, it scrolls horizontally inside its own box instead of forcing the whole page to scroll sideways.
  • The book describes this as most useful below about 768px wide (phones and small tablets).
  • Currency note: the book says Bootstrap is in its fourth version; the current release is Bootstrap 5, where .table-responsive scrolls at any width when needed and variants such as .table-responsive-md scroll only below a specific breakpoint (md is 768px). The concept is unchanged.
  • A responsive table is still a data table — it does not replace HTML5 structure elements. Bootstrap requires linking its CSS file, so treat this section as awareness rather than something students must build today.

Classroom application

Lab 5-1: Creating HTML5 tables to organize content

Goal: convert the plain-text team list on aboutus_the-team.html into a table.

  1. Set up — copy aboutus_the-team.html and the aboutus\ folder from Lesson05\Lab_5-1\ into the uCorp\ directory, at the same level as aboutus.html and index.html. View it in a browser: the team information is not tabular.
  2. Cut the content — find <h2>Our Creative Team</h2> and cut (Ctrl+X, not Delete) everything from the <p> below it through “Stella@ucorp.com,” including the <br> tags and the closing </p> — but not </article>. Paste it into a new file and save it as old.txt. Building the empty structure first and adding content later is the easiest way to learn tables.
  3. Build the skeleton — add <table></table> where the text was, leave blank lines between the tags, add a border rule so the table is visible while building, and add the caption The Men and Women who Keep uCorp Running.
  4. Plan the columns — ask students, on paper, how many columns the content needs and what to call them. Answer: three — Name, Job Title, Email Address.
  5. Header row — one <tr> containing three <th> cells, each element on its own line.
<!-- Inside the head tag -->
<style>
  table, th, td {
    border: 1px solid black;
  }
</style>

<!-- Inside the body tag -->
<table>
  <caption>
    The Men and Women who Keep uCorp Running
  </caption>
  <tr>
    <th>Name</th>
    <th>Job Title</th>
    <th>Email Address</th>
  </tr>
</table>
  1. First data row — a <tr> with three <td> cells for Jane Doe, CEO & Founder, jane@ucorp.com, copied from old.txt.
  2. Center the data with a class — not every cell will be centered, so create a class in aboutus/aboutus.css and apply it to the cells:
td.center {
  text-align: center;
}
<tr>
  <td class="center">Jane Doe</td>
  <td class="center">CEO &amp; Founder</td>
  <td class="center">jane@ucorp.com</td>
</tr>

Note: the book’s printed step shows “Jame Doe” — a typo; the name is Jane Doe. In HTML, write the ampersand as &amp; so the page validates cleanly.

  1. Intro paragraph — above the table, below the heading, add: Why are our products so popular? Because the men and women of uCorp work tirelessly to produce nothing but the best.
  2. Check and validate — view the page (caption, three columns, header row, one data row), then validate at the W3C Markup Validation Service while the file is still short and errors are easy to find.
  3. Remaining rows — add eight more rows (nine people total) from old.txt, centered. Point out that <tr> adds rows, <td> adds cells, and <th> defines the categories for each column.
  4. Finish the styling in aboutus.css:
table {
  font-family: Arial, Helvetica, Geneva, Swiss, sans-serif;
  font-size: 70%;
  width: 90%;
}

table.center {
  margin-left: auto;
  margin-right: auto;
}

td {
  padding: 5px;
}
  • The font matches the document font, at a slightly smaller size (70% instead of 80%) because tables often look better that way.
  • width: 90% leaves a margin inside the section.
  • Add class="center" to the <table> tag to center it.
  • 5px of padding adds white space around the data.
  1. Save both files, view, correct as needed, and validate again.

Lab 5-2: Customizing HTML5 tables with CSS3 formatting

Goal: make the team table easier to read and more visually appealing. Students can continue from Lab 5-1 or copy the Lab 5-2 starter files into uCorp.

  1. Bold the caption — wrap the caption text in <strong>...</strong> inside <caption>.
  2. Color the header row — set the first row’s background to light blue #6699FF. One way:
tr:first-child {
  background-color: #6699FF;
}

tr:first-child selects the first row of the table — the header row. (Preview: :first-child is a CSS pseudo-class; a class on the header row works too.)

  1. Size the first column — set the first <th> cell’s width to 93 (px), which sizes the whole Name column:
th:first-child {
  width: 93px;
}
  1. Tighten the padding — change the td padding from 5px to 3px.
  2. Experiment — background colors on cells and rows, font colors, or border-collapse: collapse so only one line surrounds each cell. The book’s sample result uses alternating blue rows.
  3. Space the footer — add <br> immediately after </table> so the footer does not crowd the table. (A CSS margin-bottom on the table is the more modern way to add that space.)
  4. If time permits — remove the table border, refresh, observe the difference, then restore it.

The habit for both labs: save, refresh, and validate after every edit. If something breaks, the last change caused it.

In-book exercises and activity

These are short drag-and-drop matching items in the online book. Use them as quick checks right after the related topic:

  • Exercise 5-1: Defining table structure (after the five table elements) — students match <table>, <caption>, <tr>, <th>, and <td> to their descriptions from Table 5-1.
  • Exercise 5-2: CSS properties for all table elements (after Lab 5-1) — two sets. The first matches border, border-collapse, border-spacing, and padding; the second matches width, text-align, and vertical-align. The book words text-align as controlling line justification and vertical-align as placement between the top and bottom of the cell, so connect those phrases to “horizontal” and “vertical” before students start.
  • Activity 5-1: Identifying HTML table attributes and properties (after column and row spanning) — students match rowspan, colspan, padding, border-spacing, and width. The attributes are described by how many rows or columns a single cell can occupy, and padding and border-spacing are the pair most often swapped, so revisit the inside-vs.-between distinction first.

Case study: To use tables or not to use tables

An-Mei supervised a team converting the company’s HTML 4.0 site to HTML5. Reviewing the pages, they found tables used to structure all content, not just tabular content. She reserved tables for content that required a structured layout — numbers, dates, spreadsheet-style lists — and had the team replace layout tables with HTML5 structure elements. It took significant time, but afterward pages were quick to update, future changes were easier, and management was pleased that updates happened faster.

Discussion prompts and target answers:

  • What content benefits from a tabular structure? What does not? Comparing numerical data and similar ideas side by side (prices, schedules, grades, specifications) benefits. Long descriptions and images usually do not.
  • Why did developers use invisible layout tables for so many years, and what are the disadvantages? They were a simple way to structure pages when CSS support in browsers was weak. They make pages much harder to modify and debug, reduce accessibility, and do not respond to different screen formats.
  • Is this situation likely in the workplace today? Less likely because CSS3 and HTML5 are universal, but many businesses still run old, outdated sites, so a new developer could inherit one.

Troubleshooting practice

Present each symptom and have students name the clue before revealing the fix:

  • Header cells are left-aligned and not bold → they were coded as <td>; change them to <th>.
  • One row merges two people’s names into a single wide cell → a colspan value is too large (or misplaced); recount the columns and fix the cell count.
  • A homepage laid out with a table confuses screen readers → rebuild the layout with header, nav, section, article, aside, and footer.
  • A table forces the whole page to scroll sideways on a phone → wrap it in <div class="table-responsive"> (Bootstrap) and size it in percentages.

Application project

Have students review an HTML tables reference and the W3C documentation for the <table> element, then browse sites that use tables. Discussion: Do those tables present information effectively? What content is best suited to tabular presentation?

Common misconceptions

  • “Tables are a good way to lay out a page.” Tables are for data. Page layout uses HTML5 structure elements and CSS.
  • “<th> is just bold text.” It marks a cell as a label, which browsers and screen readers rely on. Use it for headers even if you restyle it.
  • “border="1" is fine.” The border attribute is deprecated in HTML5 and fails validation; use the CSS border property.
  • “Tables have borders by default.” They do not; add a CSS border to see the grid.
  • “Padding and border-spacing are the same.” Padding is inside a cell; border-spacing is between cells and has no effect once borders are collapsed.
  • “text-align: center centers the table.” It only centers content inside cells; center the table with margin-left: auto and margin-right: auto.
  • “The last height rule wins.” Among cells in the same row, the largest height wins regardless of order.
  • “colspan just widens a cell.” It replaces cells; remove the cell it covers or the grid breaks.
  • “colspan and rowspan are CSS.” They are HTML attributes on <th> or <td>.
  • “Pixel widths are safest.” Percentages adapt to screen size; fixed pixel widths can overflow on phones.

Key terms

  • rowspan — an attribute used with <th> or <td> to span a cell vertically across two or more rows.
  • colspan — an attribute used with <th> or <td> to span a cell horizontally across two or more columns.
  • Bootstrap — an open-source, front-end framework of HTML and CSS design templates.
  • Responsive design — a site designed to work properly and seamlessly on all screen sizes and resolutions.
  • Deprecated — an older feature, such as the HTML border attribute, that should no longer be used and will not pass HTML5 validation.

Lesson summary

  • Use tables only for information that naturally belongs in rows and columns.
  • Build every table from <table>, <tr>, and <td>, adding <caption> for a title and <th> for labels. Close every tag and keep each row’s cell count consistent.
  • Header cells default to bold, centered text; data cells default to left-aligned, normal text. Align consistently within columns.
  • Style tables with CSS3 — border, border-collapse, border-spacing, padding, width, height, background-color, text-align, and vertical-align — never with deprecated HTML attributes.
  • Add background colors to whole tables, rows, or individual cells by choosing the right selector, and remember that border choices dramatically change a table’s appearance.
  • Size in percentages where possible, and center a table with automatic left and right margins.
  • Merge cells with colspan (across columns) and rowspan (down rows), removing the cells they replace.
  • Lay out pages with header, nav, section, article, aside, and footer; wrap wide data tables in a responsive container for small screens.
  • Save, refresh, and validate after every change.

Next lesson: Web Forms — tables organize information on a page; forms collect information from visitors.