Section 10: Tables, Captions, Headers, Spans and Accessible Data
HTML tables organize related information into rows and columns. They are useful for displaying employee records, course schedules, product comparisons, invoices, financial reports, examination results and other structured data.
In this lesson, you will learn how to create tables using semantic HTML, group table sections, identify row and column headers, merge cells using colspan and rowspan, and make tabular information accessible to people using assistive technologies.
1. Learning Objectives
By the end of this lesson, you will be able to:
- Understand when an HTML table is appropriate.
- Use table, tr, th and td correctly.
- Add descriptive captions to tables.
- Organize tables using thead, tbody and tfoot.
- Distinguish header cells from ordinary data cells.
- Use scope to identify row and column headers.
- Merge cells horizontally using colspan.
- Merge cells vertically using rowspan.
- Understand colgroup and col for column-level structure and styling.
- Use id and headers to associate cells in complex tables.
- Apply accessible table practices and test table behavior.
- Build practical data tables for real-world applications.
2. What Is an HTML Table?
An HTML table represents data arranged in rows and columns. Each cell belongs to a particular row and may contain either a heading or data.
The main HTML table elements are:
- table: the container for tabular data.
- caption: a title or description identifying the table.
- tr: a table row.
- th: a header cell.
- td: a data cell.
- thead: a group of header rows.
- tbody: a group of body rows.
- tfoot: a group of footer rows, often used for totals or summaries.
- colgroup and col: elements for identifying columns and applying column-level presentation.
3. Your First HTML Table
Let's create a simple table displaying employee information.
Example
<table>
<tr>
<th>Employee ID</th>
<th>Name</th>
<th>Department</th>
</tr>
<tr>
<td>101</td>
<td>Rahul</td>
<td>Development</td>
</tr>
<tr>
<td>102</td>
<td>Priya</td>
<td>Testing</td>
</tr>
</table>
The first row contains header cells, and the following rows contain employee data.
Browsers may apply default styling to header cells, but visual appearance alone does not determine the full accessibility of a table. Correct structure and relationships matter.
4. Understanding table, tr, th and td
The table Element
The table element contains the complete tabular structure. It should be used when information has meaningful relationships between rows and columns.
The tr Element
The tr element represents one row. It contains cells represented by th or td elements.
The th Element
The th element represents a header cell. It identifies a heading associated with one or more data cells.
The td Element
The td element represents an ordinary data cell.
Example
<table>
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>Keyboard</td>
<td>₹1,200</td>
</tr>
</table>
Here, Product and Price are column headings. Keyboard and ₹1,200 are data values.
5. Adding a Caption
The caption element provides a title or description that identifies the purpose of a table. It is particularly useful when a page contains multiple tables.
Syntax
<table>
<caption>Monthly Sales Report</caption>
<tr>
<th>Month</th>
<th>Sales</th>
</tr>
<tr>
<td>January</td>
<td>₹50,000</td>
</tr>
</table>
The caption should be the first child of the table element when used. Browsers commonly display it above the table, although CSS can change its visual position.
Writing Good Captions
A useful caption tells users what the table represents without requiring them to infer its purpose from the surrounding page.
Examples of meaningful captions:
- Employee Attendance — October 2026
- Quarterly Revenue by Department
- HTML Course Modules and Durations
- Product Prices as of October 2026
Avoid vague captions such as "Table 1" when a descriptive title would be more helpful.
6. Grouping Table Sections
HTML provides thead, tbody and tfoot to group rows according to their purpose.
thead
The thead element groups rows containing column or other table headings.
tbody
The tbody element groups the main data rows of a table.
tfoot
The tfoot element groups rows summarizing the table, such as totals or other aggregate values.
Complete Example
<table>
<caption>Monthly Sales Report</caption>
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Sales</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>₹50,000</td>
</tr>
<tr>
<td>February</td>
<td>₹65,000</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row">Total</th>
<td>₹1,15,000</td>
</tr>
</tfoot>
</table>
The table contains a caption, a header section, a body section and a summary section. The Total cell is a row heading, while the final cell contains the calculated value.
Important Notes
- These grouping elements improve document structure and can help with styling and table processing.
- A table can contain one or more tbody elements when its structure requires them.
- thead and tfoot are optional when they are not needed.
- Browsers can create an implicit tbody when table rows are written directly inside table in source markup.
- When writing maintainable HTML, explicitly grouping rows often makes the structure easier to understand.
7. Column Headers and the scope Attribute
The scope attribute on a th element identifies whether that header applies to a column, row, column group or row group.
This information helps browsers and assistive technologies interpret the relationship between headers and data.
Common scope Values
- scope="col": the header applies to its column.
- scope="row": the header applies to its row.
- scope="colgroup": the header applies to a group of columns.
- scope="rowgroup": the header applies to a group of rows.
Example: Column Headers
<table>
<caption>Student Examination Results</caption>
<thead>
<tr>
<th scope="col">Student</th>
<th scope="col">HTML</th>
<th scope="col">CSS</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Anita</th>
<td>85</td>
<td>90</td>
</tr>
<tr>
<th scope="row">Rohan</th>
<td>78</td>
<td>82</td>
</tr>
</tbody>
</table>
The first row defines the columns. Each student's name is a row header, helping users understand the values associated with that student.
When Should You Use scope?
For simple tables with clear row and column relationships, scope="col" and scope="row" make those relationships explicit. In more complex tables, additional associations may be necessary.
8. The colspan Attribute
The colspan attribute allows one cell to span multiple columns. It is useful for grouped headings, section labels and summary rows.
Basic Syntax
<td colspan="2">Combined cell</td>
The cell occupies the space of two columns in the table's grid.
Example: Grouped Heading
<table>
<caption>Course Performance</caption>
<thead>
<tr>
<th rowspan="2" scope="col">Student</th>
<th colspan="2" scope="colgroup">Scores</th>
</tr>
<tr>
<th scope="col">HTML</th>
<th scope="col">CSS</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Anita</th>
<td>85</td>
<td>90</td>
</tr>
</tbody>
</table>
The Scores heading spans the HTML and CSS columns. The Student header spans two rows using rowspan.
For semantic accuracy, grouped headers should have meaningful relationships with the cells beneath them. In complex tables, explicit header associations may be needed even when scope is present.
9. The rowspan Attribute
The rowspan attribute allows one cell to extend across multiple rows.
Basic Syntax
<td rowspan="2">Morning Shift</td>
The cell occupies two rows in the table's grid. The corresponding position in the following row is occupied by the spanning cell, so an extra cell should not be added there for the same grid position.
Example: Work Schedule
<table>
<caption>Employee Shift Schedule</caption>
<thead>
<tr>
<th scope="col">Shift</th>
<th scope="col">Employee</th>
<th scope="col">Department</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="rowgroup" rowspan="2">Morning</th>
<td>Amit</td>
<td>Development</td>
</tr>
<tr>
<td>Priya</td>
<td>Testing</td>
</tr>
<tr>
<th scope="row">Evening</th>
<td>Rahul</td>
<td>Support</td>
</tr>
</tbody>
</table>
The Morning header spans the first two data rows. In real-world tables, verify that the header's semantic meaning matches the cells it covers. A complex table may require a more explicit header-association approach.
Important Rules for Spans
- colspan controls how many columns a cell occupies.
- rowspan controls how many rows a cell occupies.
- Both attributes belong on table cells, including th and td.
- Spanning cells affect the table grid, so row structures must be planned carefully.
- A rowspan value of 0 has a special meaning: the cell extends to the end of its row group.
- Use spans only when the data relationships genuinely require them. Excessive merging can make tables difficult to understand and maintain.
10. Complex Tables and the id and headers Attributes
Simple tables often have obvious relationships between column headers, row headers and data cells. Complex tables may have multiple levels of headers, grouped columns or several header relationships for one data cell.
For these tables, a th element can have a unique id, and a td or th cell can use the headers attribute to reference one or more header IDs.
Example: Sales by Region and Quarter
<table>
<caption>Quarterly Sales by Region</caption>
<thead>
<tr>
<th id="region" rowspan="2">Region</th>
<th id="north" colspan="2">North</th>
<th id="south" colspan="2">South</th>
</tr>
<tr>
<th id="north-q1">Q1</th>
<th id="north-q2">Q2</th>
<th id="south-q1">Q1</th>
<th id="south-q2">Q2</th>
</tr>
</thead>
<tbody>
<tr>
<th id="east-region" scope="row">East</th>
<td headers="east-region north north-q1">12000</td>
<td headers="east-region north north-q2">15000</td>
<td headers="east-region south south-q1">10000</td>
<td headers="east-region south south-q2">13000</td>
</tr>
</tbody>
</table>
Each data cell references the relevant row header, group heading and individual column heading. This helps explicitly describe the relationships in a table with multiple header levels.
How headers Works
- The id attribute uniquely identifies a header cell in the document.
- The headers attribute contains a space-separated list of IDs for header cells associated with the current cell.
- Every referenced ID must exist and identify an appropriate header cell.
- Use explicit associations when simple row and column scope relationships do not adequately express the table's structure.
For simpler tables, scope is often easier to maintain. Do not add unnecessary complexity to a table whose relationships are already clear.
11. colgroup and col
The colgroup element groups columns, while col represents one or more columns within a group. These elements can help apply presentation rules to columns without repeating styles on every cell.
Example
<table>
<caption>Product Comparison</caption>
<colgroup>
<col>
<col span="2">
</colgroup>
<thead>
<tr>
<th scope="col">Feature</th>
<th scope="col">Basic</th>
<th scope="col">Premium</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Storage</th>
<td>10 GB</td>
<td>100 GB</td>
</tr>
<tr>
<th scope="row">Support</th>
<td>Email</td>
<td>Priority support</td>
</tr>
</tbody>
</table>
The colgroup identifies the columns. The span attribute on col can represent multiple consecutive columns.
Column-level styling has limitations. CSS properties that work on ordinary cells do not all apply directly to col or colgroup. Background, border and width behavior should be tested in the target browsers.
12. Styling Tables with CSS
HTML defines the table structure, while CSS controls borders, spacing, typography, colors and responsive presentation.
Example: Basic Table Styling
<style>
.sales-table {
width: 100%;
border-collapse: collapse;
}
.sales-table th,
.sales-table td {
border: 1px solid #cccccc;
padding: 10px;
text-align: left;
}
.sales-table thead {
background-color: #eeeeee;
}
.sales-table caption {
text-align: left;
font-weight: bold;
padding-bottom: 10px;
}
</style>
<table class="sales-table">
<caption>Monthly Sales</caption>
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Revenue</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>₹50,000</td>
</tr>
<tr>
<td>February</td>
<td>₹65,000</td>
</tr>
</tbody>
</table>
In a real application, place the CSS in a reusable stylesheet and use class names that describe the component.
Useful CSS Properties
- border-collapse: controls whether adjacent cell borders are collapsed.
- border-spacing: sets spacing between cell borders when borders are separate.
- padding: adds space inside cells.
- text-align: controls horizontal text alignment.
- vertical-align: controls vertical alignment of cell content.
- width and min-width: influence table sizing and minimum content width.
- caption-side: controls whether the caption is displayed at the top or bottom.
13. Responsive Tables
Tables with many columns can overflow narrow screens. A common solution is to place the table inside a horizontally scrollable container.
Example
<style>
.table-wrapper {
max-width: 100%;
overflow-x: auto;
}
.data-table {
width: 100%;
min-width: 600px;
border-collapse: collapse;
}
.data-table th,
.data-table td {
border: 1px solid #cccccc;
padding: 8px;
text-align: left;
}
</style>
<div class="table-wrapper">
<table class="data-table">
<caption>Employee Report</caption>
<thead>
<tr>
<th scope="col">Employee ID</th>
<th scope="col">Name</th>
<th scope="col">Department</th>
<th scope="col">Email</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>101</td>
<td>Rahul</td>
<td>Development</td>
<td>rahul@example.com</td>
<td>Active</td>
</tr>
</tbody>
</table>
</div>
The wrapper allows horizontal scrolling when the table is wider than the available viewport. Test keyboard access, zoom and touch interaction as well as visual layout.
For simpler tables, the layout may naturally fit the screen without scrolling. Avoid forcing every table to have a large minimum width when it is not necessary.
14. Accessibility Best Practices
Accessible tables help users understand the relationships between headings and values, including users who navigate with screen readers or other assistive technologies.
- Use tables for genuinely tabular information, not general page layout.
- Add a meaningful caption when it helps identify the table.
- Use th for header cells and td for ordinary data cells.
- Use scope="col" and scope="row" for straightforward column and row headers.
- Use id and headers when a complex table requires explicit associations.
- Keep header text descriptive and concise.
- Ensure that important meaning is not communicated by color alone.
- Check that tables remain usable at high zoom levels and on narrow screens.
- Do not use blank cells or merged cells unnecessarily to create visual spacing.
- Test complex tables with actual assistive technologies when possible.
Table Versus Page Layout
Do not use a table to arrange the general layout of a webpage, such as a header, sidebar and footer. Use semantic layout elements and CSS Grid or Flexbox for page layout.
Tables are appropriate when the relationship between rows and columns is part of the information itself, such as an invoice, a price comparison or a report.
15. Real-World Example: Invoice Table
Invoices often contain quantities, unit prices and line totals. The footer can summarize the amount due.
<table>
<caption>Invoice #INV-1001</caption>
<thead>
<tr>
<th scope="col">Item</th>
<th scope="col">Quantity</th>
<th scope="col">Unit Price</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Keyboard</th>
<td>2</td>
<td>₹1,200</td>
<td>₹2,400</td>
</tr>
<tr>
<th scope="row">Mouse</th>
<td>1</td>
<td>₹600</td>
<td>₹600</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row" colspan="3">Grand Total</th>
<td>₹3,000</td>
</tr>
</tfoot>
</table>
The Grand Total cell spans three columns. This example demonstrates a caption, column headers, row headers, a body and a footer.
In a real billing system, calculate totals using the application logic and validate the results on the server. HTML displays the data; it should not be the trusted source for financial calculations.
16. Common HTML Table Mistakes
Mistake 1: Using td for Every Heading
Using td for every cell can make it harder to communicate which cells identify rows or columns. Use th for actual header cells.
Mistake 2: Forgetting Header Associations
A table may look correct but still be difficult to understand if its row and column relationships are unclear. Use scope or explicit header associations as appropriate.
Mistake 3: Incorrect colspan Values
When a cell spans multiple columns, the remaining cells in that row must fit the resulting grid. Incorrect spans can cause the table structure to become confusing or misaligned.
Mistake 4: Incorrect rowspan Structure
A cell spanning multiple rows occupies grid positions in each of those rows. Do not add another cell in a position already occupied by the spanning cell.
Mistake 5: Using Tables for General Layout
Use CSS Grid or Flexbox for page layout. Use HTML tables for tabular data.
Mistake 6: Missing Captions or Meaningful Headings
When a table has a purpose that is not obvious from its context, add a descriptive caption and clear headers.
Mistake 7: Making Tables Too Wide
Very wide tables can become difficult to read on small screens. Consider horizontal scrolling, clearer column labels or presenting a smaller set of columns when appropriate.
Mistake 8: Confusing Styling with Semantics
Making a td cell bold does not turn it into a header cell. Use the correct HTML element to communicate meaning, then style it with CSS.
17. Practical Exercises
Exercise 1: Student Marks Table
Create a table showing five students and their marks in HTML, CSS and JavaScript. Add a caption, column headers and row headers.
Exercise 2: Monthly Sales Report
Create a report for three months. Use thead, tbody and tfoot, and include a total row.
Exercise 3: Product Comparison
Compare two products using a table. Use colspan for a grouped heading that spans both products.
Exercise 4: Employee Shift Schedule
Create a schedule with multiple employees. Use rowspan when one shift label applies to multiple consecutive employee rows.
Exercise 5: Complex Regional Report
Create a table that groups quarterly figures under two regional headings. Give the relevant headers unique IDs and use headers to associate data cells with their row and column headings.
Exercise 6: Responsive Data Table
Place a table with at least five columns inside a horizontally scrollable wrapper. Test it on a narrow screen or by resizing your browser.
Exercise 7: Debug the Table
Identify and correct the structural and semantic issues in the following example.
<table>
<tr>
<td>Name</td>
<td>Marks</td>
</tr>
<tr>
<th colspan="2">Rahul</th>
<td>85</td>
</tr>
</table>
Think about which cells are headings, whether the number of columns is consistent and whether the table needs a caption.
18. Section 10 Quiz: Test Your Understanding
Answer all 10 questions before reading the answer key. The quiz covers table structure, captions, headers, spans, grouping elements, accessibility and responsive behavior.
Question 1: Basic Table Structure
Which element represents a row in an HTML table?
<td><tr><th><tbody>
Question 2: Table Captions
What is the primary purpose of the caption element?
- To merge cells
- To identify or describe the table
- To create a new column
- To replace every th element
Question 3: Table Header Groups
Which element groups the main body rows of a table?
<thead><tfoot><tbody><caption>
Question 4: Column and Row Headers
Which scope values are most commonly used to identify a simple column header and a simple row header?
- scope="top" and scope="left"
- scope="col" and scope="row"
- scope="column" and scope="line"
- scope="head" and scope="body"
Question 5: colspan
What does colspan="3" mean when applied to a table cell?
- The cell occupies three rows.
- The cell occupies three columns.
- The table contains three header rows.
- The cell is hidden on three devices.
Question 6: rowspan
What does rowspan="2" mean when applied to a table cell?
- The cell occupies two columns.
- The cell occupies two rows.
- The cell contains two values.
- The table has two captions.
Question 7: True or False
The headers attribute can reference the IDs of header cells associated with a data cell.
- True
- False
Question 8: Column Groups
Which elements are used to group columns and identify columns within a group?
- thead and tbody
- tr and td
- colgroup and col
- dl and dt
Question 9: Accessibility
Which is the best approach for a complex table with multiple levels of headers?
- Use only td elements and rely on bold text.
- Remove all captions and headings.
- Use meaningful header cells and explicit header associations when needed.
- Use a table only for page layout.
Question 10: Responsive Tables
What is a common way to make a wide data table usable on narrow screens?
- Remove all table rows.
- Place the table inside a container that allows horizontal scrolling when needed.
- Replace every cell with a heading.
- Use rowspan on every cell.
19. Quiz Answer Key and Explanations
Review the correct answers and explanations below. Understanding why an answer is correct is more valuable than memorizing the letter.
Answer 1: B — tr
The tr element represents a table row. It contains table header cells or data cells. The td and th elements represent individual cells, while tbody groups body rows.
Answer 2: B — To identify or describe the table
The caption element provides a title or description that helps users understand the table's purpose. It is particularly useful when a page contains multiple data tables.
Answer 3: C — tbody
The tbody element groups the main data rows. Thead groups header rows, while tfoot groups footer or summary rows.
Answer 4: B — scope="col" and scope="row"
scope="col" identifies a header associated with a column, and scope="row" identifies a header associated with a row. These values are commonly used in simple data tables.
Answer 5: B — The cell occupies three columns
The colspan attribute controls the number of columns occupied by a table cell. It is useful for grouped headings and summary cells that span multiple columns.
Answer 6: B — The cell occupies two rows
The rowspan attribute controls the number of rows occupied by a cell. Other cells must be arranged around the spanning cell so that the table grid remains correct.
Answer 7: True
The headers attribute contains a space-separated list of IDs identifying header cells associated with the current cell. This is useful when a table has relationships that are too complex to communicate with simple scope values alone.
Answer 8: C — colgroup and col
colgroup groups columns, while col identifies one or more columns within a group. These elements can help with column-level styling and structural organization.
Answer 9: C — Use meaningful header cells and explicit header associations when needed
Complex tables require clear relationships between data and the relevant headers. Meaningful th elements, unique IDs and the headers attribute can provide explicit associations when necessary.
Answer 10: B — Use a horizontally scrollable container when needed
A wrapper with overflow-x: auto allows a wide table to scroll horizontally on narrow screens. This preserves the tabular structure while making the content more usable on smaller devices.
20. Final Revision Checklist
- I understand table, tr, th and td.
- I can add a meaningful caption.
- I can organize rows using thead, tbody and tfoot.
- I understand the difference between row and column headers.
- I can use scope to clarify simple header relationships.
- I can merge cells using colspan and rowspan.
- I understand how id and headers support complex tables.
- I know the purpose of colgroup and col.
- I can style tables with CSS and make wide tables usable on small screens.
- I understand why tables should represent data rather than general page layout.
- I have completed the practical exercises and reviewed all 10 quiz answers.
Lesson Completion
Congratulations! You have completed Section 10 of Codementrix HTML5 Mastery.
You now understand how to build structured HTML tables, add captions, identify headers, merge cells and improve accessibility for tabular data.
Next lesson: Section 11 — Semantic HTML5.