A simple data table, with a single row of column headers at the top, is relatively straightforward to make accessible. The real pain starts with complex tables — ones with headers in both columns and rows, merged cells, or summary rows. This article explains how to tag table headers so a screen reader "understands," for every cell, which headers apply to it, without losing context.

In short — what this guide covers

  1. Why TH is different from TD
  2. When scope is enough, and when you need more
  3. Summary rows and multiple headers
  4. How this looks in practice in Word and PDF

Why TH Is Different from TD

In an HTML table or a tagged PDF, every cell has one of two role types: TH (Table Header) or TD (Table Data — a regular data cell). The difference isn't necessarily visual — a header cell and a data cell can look identically styled — it's semantic: TH tells the screen reader "this is a header that explains what the data below or beside it means." Without correct tagging, a screen reader moves through the table row by row as if every cell were equal, and it's easy to completely lose track of which data belongs to which category.

When scope Is Enough, and When You Need More

For most tables, you add a scope attribute to every TH cell to indicate whether it's a column header (scope="col") or a row header (scope="row"). When a screen reader reaches a data cell, it automatically announces both the relevant column header and row header — so the user hears, for example, "1,200 — Sales, Q1" instead of just an isolated "1,200."

For especially complex tables, with more than two levels of headers (for example, a super-header that groups several sub-columns), scope alone isn't always enough. In those cases, use the pair of attributes id and headers: give every header cell a unique id, and in every data cell list, in the headers attribute, all the header ids relevant to it. This method is more flexible but also more complex and error-prone — reserve it for cases that truly need it.

Illustrative diagram Tagging table headers with scope Example of a data table with tagged column and row headers Header Cells (TH) vs. Regular Data Cells (TD) Quarter Product Sales Q1 Q2 Q3 Documents Websites Documents 1,200 950 1,480 scope="col" scope="row" Column headers get scope="col" and row headers get scope="row" — so the screen reader announces both for every cell
In this table: the column headers ("Quarter," "Product," "Sales") are tagged with scope="col", and the row headers ("Q1," "Q2," "Q3") with scope="row" — so every data cell is linked to the two headers relevant to it.

Summary Rows and Multiple Headers

A summary row at the bottom of a table ("Total," "Average") is itself a kind of header — it's usually appropriate to tag the total cell itself as TH with scope="row", so a screen reader distinguishes it from a regular data row. Similarly, a table with a super-header that groups several columns (for example, "2026 Sales" spanning "Q1," "Q2") requires correct use of the colspan attribute together with scope, so the hierarchical grouping is preserved when it's read aloud too.

💡 Practical Tip

If a table feels too complicated to tag correctly (more than two levels of headers, multiple merges), sometimes the simplest and most accessible solution is to break it into several simpler tables, or add a plain-text summary alongside it.

How This Looks in Practice in Word and PDF

In Word, using the standard "Insert ▸ Table" tool and checking "Header Row" in Table Design creates the correct foundation, which exports to PDF as TH automatically in most cases. In Acrobat, after exporting from Word and running an accessibility check, it's worth opening the tags tree and confirming that the header cells were indeed marked as TH and not as a regular TD — this is a common export mistake that's easy to miss.

Have Data Tables in Documents That Have Never Been Tested?

Our tool identifies tables with missing or incorrect headers across every PDF file on your site.

Scan your site for free ←