HTML Table Basics: Building Semantic Tables with <table>, <tr>, <th>, and <td>
HTML tables are the standard way to present data that belongs in rows and columns, such as schedules, price lists, reports, and comparison charts. This article shows you how to build tables correctly, add headers and captions, and keep your markup accessible and semantic.
Quick answer: Use <table> for tabular data, <tr> for rows, <th> for header cells, and <td> for regular data cells. Add <caption> for a short table description and use scope or structural headings to make the table easier to understand with screen readers.
Difficulty: Beginner
You'll understand this better if you know: basic HTML elements, how attributes work, and the difference between content meant for layout versus content meant for data.
1. What Are HTML Table Basics?
HTML table basics cover the core elements and rules for writing tables in HTML. A proper table is not just a grid on the page; it is structured data with relationships between headers and cells.
- <table> wraps the entire table.
- <tr> defines a table row.
- <th> defines a header cell.
- <td> defines a data cell.
- <caption> gives the table a readable title or summary.
These elements work together to help browsers, assistive technologies, and developers understand how the table is organized.
2. Why HTML Table Basics Matter
Tables are important because they communicate relationships that would be hard to express with paragraphs or lists. When used correctly, they make data easier to scan, compare, and reference.
Good table structure also improves accessibility. Screen readers can announce headers and navigate cells more effectively when the markup is semantic and consistent.
Tables should be used for data, not for page layout. Using tables to position page sections makes the HTML harder to maintain and often creates accessibility problems.
3. Core Table Structure and Syntax
A simple HTML table follows a predictable pattern. The table element contains rows, and each row contains header or data cells.
Basic table skeleton
This example shows the minimum structure of a semantic table with a caption and a header row.
<table>
<caption>Monthly expenses</caption>
<tr>
<th scope="col">Category</th>
<th scope="col">Amount</th>
</tr>
<tr>
<td>Rent</td>
<td>$1,200</td>
</tr>
</table>The caption describes the table, the first row uses header cells, and the data rows use regular cells. That structure is enough for many simple tables.
What each element does
<table> is the container. <tr> marks a row. <th> labels a column or row. <td> contains the actual values.
The scope attribute helps clarify whether a header applies to a column or a row. This is especially useful when the table has more than one header direction.
4. Step-by-Step Examples
The following examples show how table basics work in real situations. Each one uses the same core elements, but the structure changes based on the data.
Example 1: A simple product list
This table lists products and prices. It is the most common beginner-friendly pattern: one header row and several data rows.
<table>
<caption>Featured products</caption>
<tr>
<th scope="col">Product</th>
<th scope="col">Price</th>
</tr>
<tr>
<td>Notebook</td>
<td>$4.99</td>
</tr>
<tr>
<td>Pen</td>
<td>$1.49</td>
</tr>
</table>This version is easy to read and easy for assistive technology to interpret. Each column has a clear label.
Example 2: A schedule table with row headers
Sometimes the first column is also a header column. In that case, use <th> in the leftmost cells too.
<table>
<caption>Class schedule</caption>
<tr>
<th scope="col">Day</th>
<th scope="col">Topic</th>
<th scope="col">Time</th>
</tr>
<tr>
<th scope="row">Monday</th>
<td>HTML basics</td>
<td>9:00 AM</td>
</tr>
</table>The first cell in the data row is a header because it labels the row. This pattern helps readers understand which row they are looking at.
Example 3: A table with grouped information
When rows belong to different categories, you can group them visually and structurally. This table keeps the data readable without adding unnecessary complexity.
<table>
<caption>Support hours</caption>
<tr>
<th scope="col">Team</th>
<th scope="col">Available</th>
</tr>
<tr>
<td>Billing</td>
<td>Mon-Fri, 8 AM-5 PM</td>
</tr>
<tr>
<td>Technical</td>
<td>24/7</td>
</tr>
</table>This layout is useful when the table has a small number of columns and the rows are the main thing the user compares.
Example 4: A compact comparison table
Tables are often used to compare features, plans, or options. A clear header row and consistent cell content make the comparison easier to scan.
<table>
<caption>Plan comparison</caption>
<tr>
<th scope="col">Feature</th>
<th scope="col">Basic</th>
<th scope="col">Pro</th>
</tr>
<tr>
<th scope="row">Email support</th>
<td>No</td>
<td>Yes</td>
</tr>
</table>The row headers make it obvious what each row is about, which reduces confusion in wider tables.
5. Practical Use Cases
HTML table basics are useful whenever the content is organized as data rather than as flowing text.
- Product catalogs with names, prices, and availability.
- Class schedules, calendars, and timetables.
- Financial reports with rows of values and labeled columns.
- Comparison tables for plans, features, or specifications.
- Inventory lists, attendance records, and score sheets.
If you can describe the content as rows and columns that someone needs to compare, a table is probably the right element.
6. Common Mistakes
Mistake 1: Using tables for page layout
New developers sometimes use tables to position headers, sidebars, and page sections. That may seem convenient at first, but it creates rigid markup that is harder to maintain and less accessible.
Problem: This table is being used to arrange page layout instead of tabular data, which makes the HTML harder to read and can confuse assistive technology.
<table>
<tr>
<td>Site logo</td>
<td>Navigation</td>
</tr>
<tr>
<td>Main content</td>
<td>Sidebar</td>
</tr>
</table>Fix: Use semantic layout elements like <header>, <nav>, <main>, <aside>, and <footer> instead.
<header>Site logo</header>
<nav>Navigation</nav>
<main>
<article>Main content</article>
</main>
<aside>Sidebar</aside>The corrected version works because it uses elements that match the meaning of the content.
Mistake 2: Putting data cells where header cells belong
If you use <td> for headings, the table still appears on the page, but the relationships between rows and columns become less clear.
Problem: This table does not identify the headers, so screen readers and other tools have less information about how the cells relate.
<table>
<tr>
<td>Name</td>
<td>Email</td>
</tr>
<tr>
<td>Ava</td>
<td>[email protected]</td>
</tr>
</table>Fix: Use <th> for header cells, and add scope when it improves clarity.
<table>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
</tr>
<tr>
<td>Ava</td>
<td>[email protected]</td>
</tr>
</table>The corrected version clearly marks the headers, which makes the table easier to interpret.
Mistake 3: Omitting a caption or table context
When a table appears in a long page, readers may not immediately know what it is about. A missing caption is not a browser error, but it is a common usability problem.
Problem: The table has no caption or descriptive text, so the purpose of the data may not be obvious to sighted users or screen reader users.
<table>
<tr>
<th scope="col">Month</th>
<th scope="col">Revenue</th>
</tr>
<tr>
<td>January</td>
<td>$12,400</td>
</tr>
</table>Fix: Add a short caption that explains what the data represents.
<table>
<caption>Monthly revenue report</caption>
<tr>
<th scope="col">Month</th>
<th scope="col">Revenue</th>
</tr>
<tr>
<td>January</td>
<td>$12,400</td>
</tr>
</table>The corrected version works better because the caption gives the table immediate context.
7. Best Practices
Practice 1: Use tables only for true tabular data
Reserve tables for content that naturally belongs in rows and columns. This keeps your HTML honest and makes the document easier to maintain.
<table>
<caption>Office locations</caption>
<tr>
<th scope="col">City</th>
<th scope="col">Phone</th>
</tr>
</table>This matters because semantic accuracy improves accessibility and makes future edits less confusing.
Practice 2: Include a caption for context
A caption helps users understand the table before they inspect individual cells. It is especially useful when several tables appear on the same page.
<table>
<caption>Q3 attendance summary</caption>
<tr>
<th scope="col">Team</th>
<th scope="col">Present</th>
</tr>
</table>This helps both sighted users and screen reader users identify the purpose of the data quickly.
Practice 3: Keep header relationships obvious
When a table has more than one level of meaning, use row and column headers consistently. This prevents ambiguity as the table grows.
<table>
<caption>Weekly activity</caption>
<tr>
<th scope="col">Day</th>
<th scope="col">Steps</th>
</tr>
<tr>
<th scope="row">Monday</th>
<td>8,200</td>
</tr>
</table>This approach makes the table easier to scan and less error-prone when new rows are added.
8. Limitations and Edge Cases
- Tables are not ideal for responsive page layout because they do not reflow as naturally as semantic layout elements.
- Very wide tables can be hard to read on small screens unless they are redesigned or placed in a scrollable container.
- Complex tables with multiple header levels may require extra care with header associations.
- Nested tables are allowed, but they can be difficult to read and should be used only when the data structure truly requires them.
- Cell merging with rowspan and colspan can make a table harder to maintain if overused.
Note: Some browsers render table spacing and alignment slightly differently when content is long or when cells contain form controls, so test your table in the environments where it will be used.
9. Practical Mini Project
Let’s build a small, complete pricing table that uses a caption, column headers, row headers, and consistent data cells. This is a realistic pattern for landing pages and product comparisons.
<table>
<caption>Subscription pricing</caption>
<tr>
<th scope="col">Plan</th>
<th scope="col">Monthly cost</th>
<th scope="col">Support</th>
</tr>
<tr>
<th scope="row">Starter</th>
<td>$9</td>
<td>Email only</td>
</tr>
<tr>
<th scope="row">Business</th>
<td>$29</td>
<td>Priority email</td>
</tr>
</table>This table is complete enough to be useful in a real page, but still simple enough to understand at a glance. It also shows the most important table basics in one place.
10. Key Points
- Use <table> for data arranged in rows and columns.
- Use <tr> for rows, <th> for headers, and <td> for data.
- Add <caption> when the table needs a short description.
- Use scope to clarify whether headers apply to rows or columns.
- Do not use tables for general page layout.
- Keep table structures simple unless the data truly requires more complex markup.
11. Practice Exercise
Create a table for a fictional bookstore inventory with these requirements:
- A caption that names the table.
- Three column headers: Book, Author, and Stock.
- At least three rows of data.
- Use <th> for the headers and <td> for the values.
Expected output: A semantic table that clearly lists book inventory data and can be understood without extra explanation.
Hint: Start with the caption, then write the header row, then add one row per book.
Solution:
<table>
<caption>Bookstore inventory</caption>
<tr>
<th scope="col">Book</th>
<th scope="col">Author</th>
<th scope="col">Stock</th>
</tr>
<tr>
<td>HTML and CSS Basics</td>
<td>A. Rivera</td>
<td>12</td>
</tr>
<tr>
<td>Accessible Web Design</td>
<td>M. Chen</td>
<td>8</td>
</tr>
<tr>
<td>Modern HTML Reference</td>
<td>J. Patel</td>
<td>5</td>
</tr>
</table>12. Final Summary
HTML table basics are about structuring data clearly, not just drawing a grid on the page. A well-built table uses <table>, <tr>, <th>, and <td> in a way that matches the meaning of the content.
For most tables, the best starting point is simple: add a caption, use header cells for labels, and keep each row consistent. That approach makes the table easier to read, easier to maintain, and much more accessible.
If you want to go further, the next step is learning how rowspan, colspan, and more advanced table accessibility patterns work in larger tables.