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

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

Related lessons