Skip to content

<th> - Table Header Cell Element

Table Element

The <th> element defines a header cell in a table. Header cells label rows or columns and provide crucial context for understanding the data in <td> cells. The <th> element is essential for creating accessible tables, as it helps screen readers associate data with its corresponding labels.

Result
<!-- Column header -->
<th scope="col">Column Name</th>
<!-- Row header -->
<th scope="row">Row Name</th>
<!-- Header for column group -->
<th scope="colgroup">Group Name</th>
<!-- Header for row group -->
<th scope="rowgroup">Group Name</th>

The scope attribute specifies whether the header cell applies to a column, row, or group. This is the most important attribute for accessibility.

scope="col" - Header for a column

<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
</tr>
</thead>

These attributes allow header cells to span multiple columns or rows:

  • colspan - Number of columns the header spans
  • rowspan - Number of rows the header spans

For complex tables, the headers attribute explicitly associates data cells with header cells using IDs.

Provides an abbreviated version of the header content for screen readers:

<th abbr="Temp">Temperature (°C)</th>

The <th> element supports all global HTML attributes.

Result
Result
Result
Result
Result

For tables where scope isn’t sufficient, use the headers attribute:

Result
Result
Result
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tr>
<td><strong>January</strong></td>
<td>$10,000</td>
</tr>

When properly marked up with <th> and scope, screen readers announce:

  • Column header: “Name, column header”
  • Row header: “January, row header”
  • Data cell: “January, $10,000”

Without proper markup, screen readers would just say “$10,000” with no context.

/* Basic header styling */
th {
background-color: #2c3e50;
color: white;
font-weight: bold;
padding: 12px;
text-align: left;
}
/* Column headers */
thead th {
background-color: #34495e;
text-align: center;
}
/* Row headers */
tbody th {
background-color: #ecf0f1;
color: #2c3e50;
text-align: left;
}
/* Sortable headers */
th.sortable {
cursor: pointer;
user-select: none;
}
th.sortable:hover {
background-color: #4a5f7f;
}
/* Header with icon */
th::after {
content: '';
opacity: 0.5;
}
/* Sticky headers */
thead th {
position: sticky;
top: 0;
z-index: 10;
}
/* Headers with borders */
th {
border: 2px solid #34495e;
border-bottom: 3px solid #2c3e50;
}

Always Use scope

Every <th> should have a scope attribute (col, row, colgroup, or rowgroup).

Use for Both Axes

Use <th> for column headers AND row headers, not just columns.

Provide Abbreviations

Use the abbr attribute for long header text to improve screen reader experience.

Keep Text Concise

Header text should be short and descriptive. Avoid full sentences.

Visual Distinction

Style headers differently from data cells (bold, background color, etc.).

Test with Screen Readers

Always test complex tables with actual screen reader software.

<!-- ❌ Bad -->
<tr>
<td><strong>Product Name</strong></td>
<td><strong>Price</strong></td>
</tr>
<!-- ✅ Good -->
<tr>
<th scope="col">Product Name</th>
<th scope="col">Price</th>
</tr>
<!-- ❌ Bad -->
<th>Name</th>
<!-- ✅ Good -->
<th scope="col">Name</th>
<!-- ❌ Bad: using th for regular data -->
<tr>
<th>Product A</th>
<th>$19.99</th>
</tr>
<!-- ✅ Good: only first cell is a header -->
<tr>
<th scope="row">Product A</th>
<td>$19.99</td>
</tr>

The <th> element is supported in all browsers:

  • ✅ Chrome (all versions)
  • ✅ Firefox (all versions)
  • ✅ Safari (all versions)
  • ✅ Edge (all versions)
  • ✅ Opera (all versions)
  • ✅ Internet Explorer (all versions)

The scope and headers attributes are also universally supported.