Complex Tables
An accessible data table uses semantic structure — <caption> , <thead> , and <th scope> header cells — so screen readers can announce each cell's row and column, while CSS keeps the table readable and responsive on small screens.
Part of the free HTML & CSS course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What it does
< caption >
Title announced before the table by screen readers
< thead > / < tbody > / < tfoot >
Group header, data, and summary rows
scope="col" / "row"
Links a < th > to its column or row for accessibility
border-collapse: collapse
Merges cell borders into single shared lines
tr:nth-child(even)
Selects every second row for zebra striping
tr:hover
Highlights the row under the cursor
position: sticky; top: 0
Pins the header while the container scrolls
overflow-x: auto
Lets a wide table scroll sideways on mobile
content: attr(data-label)
Reprints the column name in the stacked-card pattern
colspan / rowspan
Merge cells horizontally / vertically
Frequently Asked Questions
🎉 Lesson Complete
- ✅ Use < caption > , < thead > , < tbody > , < tfoot > for semantic structure
- ✅ Add scope="col" and scope="row" to every < th > for accessibility
- ✅ Zebra striping with :nth-child(even) plus tr:hover makes data easy to scan
- ✅ position: sticky; top: 0 pins headers in a scrollable container
- ✅ data-label + ::before turn rows into mobile cards; overflow-x: auto is the simple fallback
- ✅ colspan merges horizontally, rowspan merges vertically
- ✅ Next lesson: Print Styles for export-friendly layouts
Practice quiz
Which table section element marks the header rows?
- <tbody>
- <tfoot>
- <thead>
- <caption>
Answer: <thead>. <thead> groups the header rows; <tbody> holds the data and <tfoot> the summary/total rows.
What does scope="col" on a <th> mean?
- This header labels the whole column below it
- This header labels the row to its right
- This cell spans multiple columns
- This is the table caption
Answer: This header labels the whole column below it. scope="col" tells assistive tech the header labels the column beneath it; scope="row" labels the row.
Which CSS declaration merges adjacent cell borders into single shared lines?
- border-merge: on
- border-spacing: 0
- border-style: shared
- border-collapse: collapse
Answer: border-collapse: collapse. border-collapse: collapse merges adjacent borders so you don't get doubled lines and gaps.
Which selector applies zebra striping to every second row?
- tr:hover
- tr:nth-child(even)
- tr:first-child
- tr:checked
Answer: tr:nth-child(even). tr:nth-child(even) selects every second row, the standard way to add zebra striping.
What three things does position: sticky need to pin a table header while scrolling?
- position: sticky, a top value, and a scrolling ancestor
- display: flex, a width, and z-index
- overflow: hidden and a fixed height
- float: top and a margin
Answer: position: sticky, a top value, and a scrolling ancestor. Sticky needs position: sticky plus a top value, and a scrollable ancestor with no overflow:hidden in between.
In the stacked-card responsive pattern, what reprints the column name next to each value?
- the <caption> element
- scope="row"
- content: attr(data-label) on td::before
- a second <thead>
Answer: content: attr(data-label) on td::before. td::before with content: attr(data-label) reprints each column's name once the <thead> is hidden on mobile.
Which is the simplest way to keep a wide table usable on a narrow phone?
- Delete some columns
- Wrap it in a div with overflow-x: auto
- Use display: none on the table
- Set the table width to 100vw
Answer: Wrap it in a div with overflow-x: auto. Wrapping the table in a container with overflow-x: auto lets it scroll sideways instead of breaking the layout.
What does colspan="3" do to a table cell?
- Merges it down across 3 rows
- Repeats it 3 times
- Adds 3px of padding
- Merges it across 3 columns
Answer: Merges it across 3 columns. colspan merges a cell horizontally across the given number of columns; rowspan merges vertically.
Which element gives a table a title that screen readers announce before the cells?
- <title>
- <caption>
- <legend>
- <header>
Answer: <caption>. <caption>, placed inside the table, provides a title announced before the table's contents.
When should you NOT use a <table>?
- For financial reports
- For schedules
- For page layout
- For comparison charts
Answer: For page layout. Tables are for genuinely tabular data; using them for page layout is a 1990s anti-pattern — use Grid or Flexbox.
Continue this course
- Previous: Modern Layouts
- Next: Print Styles