HTML Table Headers
In this page:
The Basic th Element
<th> works exactly like <td> structurally -- it is a table cell -- but it carries the semantic meaning of "this cell is a label," which browsers render in bold, centered text by default, and which assistive technology announces distinctly from ordinary data cells.
Note: Use <th> for every cell that labels a row or column, and reserve <td> strictly for the actual data values themselves.
Warning: A <td> styled to look bold and centered with CSS still lacks the semantic header meaning that <th> provides to screen readers.
Example: The Basic th Element
<table>
<tr>
<th>Name</th>
<td>Alex</td>
</tr>
</table>
Clarifying Direction with the scope Attribute
The scope attribute on a <th> element explicitly states whether it labels an entire column (scope="col") or an entire row (scope="row"), removing any ambiguity for screen reader users navigating a table with headers on both axes at once.
Note: Always add scope to header cells in any table that has both a header row and a header column, since that is when direction becomes genuinely ambiguous.
Warning: Skipping scope on a table with two-directional headers can make screen reader announcements confusing or ambiguous for users relying on them.
Example: Clarifying Direction with the scope Attribute
<table>
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
</tr>
</table>
Grouping with thead
<thead> wraps the header row(s) of a table in a distinct semantic section, separate from the actual data rows. This grouping is useful both for styling the header differently (like a different background color) and for browsers that support repeating the header row when a long table is printed across multiple pages.
Note: Wrap your header row in <thead> even on small tables, as a consistent habit that pays off the moment a table grows large.
Warning: A table can technically render fine without <thead>, but omitting it loses the semantic and print-repeating benefits for larger tables.
Example: Grouping with thead
<table>
<thead>
<tr><th>Name</th></tr>
</thead>
</table>
Grouping with tbody and tfoot
<tbody> wraps the main data rows of a table, while <tfoot> wraps a footer row, commonly used for totals or summary values. Together with <thead>, these three sections divide a table into clearly labeled zones, each independently stylable and, in some layouts, independently scrollable.
Note: Place <tfoot> for a totals row even though it appears visually at the bottom, since some browsers render it at the bottom of the table regardless of its position in the markup.
Warning: A table with many rows but no <tbody> wrapper misses out on the ability to independently scroll or style just the body rows.
Example: Grouping with tbody and tfoot
<table>
<tbody>
<tr><td>Apple</td></tr>
</tbody>
<tfoot>
<tr><td>Total</td></tr>
</tfoot>
</table>
Accessible Multi-Level Headers with headers and id
For complex tables where a single data cell relates to more than one header (like both a row label and a column label), the id attribute on each <th> combined with the headers attribute on a <td> creates an explicit link, letting screen readers announce every relevant header for that specific cell.
Note: Reserve the id/headers technique for genuinely complex tables; simple tables are usually clear enough with scope alone.
Warning: Typos in a headers attribute value that do not match any existing th id will silently fail to associate, with no visible error.
Example: Accessible Multi-Level Headers with headers and id
<table>
<tr>
<th id="name">Name</th>
</tr>
<tr>
<td headers="name">Alex</td>
</tr>
</table>
- Using a bold, styled <td> instead of a real <th> element for header cells, which looks the same visually but loses the semantic meaning screen readers rely on.
- Forgetting the scope attribute on header cells in complex tables, making it ambiguous whether a header applies to its row or its column.
- Placing header cells outside of a <thead> section, which loses the semantic grouping benefit for large tables with many data rows.
- <th> marks a cell as a header, rendering bold and centered by default and carrying semantic meaning for screen readers.
- The scope attribute (scope="col" or scope="row") clarifies whether a header describes an entire column or an entire row.
- <thead>, <tbody>, and <tfoot> group header rows, body rows, and footer rows semantically and enable independent styling and scrolling.
<th>, <thead>, <tbody>, <tfoot>, and the scope attribute are supported in every browser and have been part of HTML since HTML4.
Chapter Quiz — Complete all 26 topics to unlock
0/26 topics done
Complete these topics first:
- HTML Favicon
- HTML Page Title
- HTML Tables
- HTML Lists
- HTML Block & Inline
- HTML Comments
- HTML Colors
- HTML CSS
- HTML Links
- HTML Images
- HTML RGB Colors
- HTML HEX Colors
- HTML HSL Colors
- HTML Link Colors
- HTML Link Bookmarks
- HTML Background Images
- HTML Table Borders
- HTML Table Sizes
- HTML Table Headers
- HTML Table Padding & Spacing
- HTML Colspan & Rowspan
- HTML Table Styling
- HTML Table Colgroup
- HTML Unordered Lists
- HTML Ordered Lists
- HTML Other Lists / Description Lists