Tables

Tables present data in rows and columns: timetables, price lists, sports results, comparison charts. HTML tables have a clear structure of rows, header cells and data cells — and using them correctly lets screen readers announce which header each value belongs to.

Basic table structure

Try it yourself
Result
  • <table> wraps the whole table.
  • <tr> ("table row") holds one row.
  • <th> ("table header") is a heading cell — bold and centred by default.
  • <td> ("table data") is an ordinary cell.

Every row should have the same number of cells (unless cells span several columns — next lesson).

Adding borders and spacing with CSS

Unstyled tables have no borders. A few lines of CSS make them readable:

Try it yourself
Result

border-collapse: collapse merges neighbouring borders into single lines. Alternating row colours ("zebra stripes") help eyes follow long rows.

Row headers and scope

Headers aren't only along the top. When the first column labels each row, make those cells <th> too, and use scope to say which direction each header applies to:

Try it yourself
Result

A screen reader on the "1 TB" cell can now announce "Pro, Storage, 1 TB". scope="col" means the header labels its column; scope="row" labels its row.

Captions

Try it yourself
Result

<caption> must be the first thing inside the table. It acts as the table's title and is announced by screen readers — the equivalent of alt text for a table.

Tables are for data, not layout

In the early web, tables were used to arrange whole page layouts into columns. That makes pages hard to use with screen readers, hard to make responsive, and hard to maintain. Use CSS (Flexbox and Grid, lesson 25) for layout, and tables only for genuinely tabular data — information you'd put in a spreadsheet.

Wide tables on small screens

Tables with many columns don't fit on phones. The simplest robust fix is to let the table scroll sideways inside a wrapper:

Try it yourself
Result

Labelling the <section> with aria-label makes it a named region for screen readers, and tabindex="0" lets keyboard users focus it and scroll with the arrow keys.

Try it yourself

Add a row for Sunday, and a caption:

Try it yourself
Result