W3docs

HTML <th> Tag

The HTML <th> tag defines a table header cell. Learn colspan, rowspan, and the scope attribute for accessible tables, with runnable examples.

The <th> tag specifies a header cell in an HTML table. It must be used as a child element of <tr>, which, in turn, is placed inside the <table> tag. To define a standard data cell, the <td> tag is used.

This page covers what <th> does, how to span cells with colspan and rowspan, and — most importantly — how to make table headers accessible with the scope attribute and the id/headers pattern so screen readers can announce the right header for every cell.

The <th> tag can contain text, images, forms, links, or any other HTML element that can be used in the body of an HTML document. The size of the table is automatically adjusted based on the size of its content.

In HTML tables, data is arranged vertically in columns. If you want to display the first row of the table as labels or headings, you must use <th> elements instead of <td> elements for that row. By default, the content of the <th> tag is bold and centered. To change its appearance, you can use CSS styles. Table headings can also be easily styled independently from the rest of the table contents.

Note that all rows in a table should have the same number of cells. If a row has fewer cells, the browser renders the missing cells implicitly. These implicit cells inherit the table's border styles. If you need to indicate that other cells contain no data, create empty cells where necessary. If implicit cells appear consecutively, they may render as a single merged cell.

Syntax

The <th> tag comes in pairs. The content is written between the opening (<th>) and closing (</th>) tags.

HTML <th> Tag

<table> 
  <tr> 
    <th>...</th> 
  </tr> 
</table>

Example of the HTML <th> tag:

Month and Date — Example of the HTML <th> Tag — W3Docs

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      table {
        width: 80%;
        margin: 30px auto;
        border-collapse: collapse;
      }
      thead {
        background-color: #1c87c9;
        color: #fff;
      }
      th,
      td {
        padding: 10px;
        border: 1px solid #666;
      }
    </style>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <th>Month</th>
          <th>Date</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>June</td>
          <td>18.07.2018</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

Result

Rendered HTML table with Month and Date header cells

In this example, our headings are "Month" and "Date", which we define using <th> tags. We place both tags inside a <tr> element.

The colspan attribute is generally used with the <th> tag to let the content span over multiple columns. Let’s see this in action.

Example of the HTML <th> tag with the colspan attribute:

Example with a colspan attribute — HTML <th> Tag — W3Docs

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      table {
        width: 80%;
        margin: 30px auto;
        border-collapse: collapse;
      }
      tr {
        background-color: #1c87c9;
        color: #ffffff;
      }
      th,
      td {
        padding: 10px;
        border: 1px solid #666;
      }
    </style>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <th colspan="2">Month and Date</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Jun</td>
          <td>18.07.2014</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

In this example, the value of the colspan attribute is "2". It means that the single header cell stretches across two columns.

Example of the HTML <th> tag with the rowspan attribute

The rowspan attribute is the vertical counterpart of colspan: it makes a header cell span multiple rows. This is useful when one heading applies to several rows of data.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      table {
        border-collapse: collapse;
        margin: 30px auto;
      }
      th,
      td {
        padding: 10px;
        border: 1px solid #666;
      }
      thead {
        background-color: #1c87c9;
        color: #fff;
      }
    </style>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <th>Day</th>
          <th>Slot</th>
          <th>Activity</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th rowspan="2" scope="rowgroup">Monday</th>
          <td>Morning</td>
          <td>HTML basics</td>
        </tr>
        <tr>
          <td>Afternoon</td>
          <td>CSS basics</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

Here the "Monday" header cell uses rowspan="2", so it covers both the morning and afternoon rows.

The scope attribute

The single most important accessibility feature of <th> is the scope attribute. It tells assistive technology — screen readers in particular — which cells a header describes. Sighted users infer this from layout, but a screen reader reads cells one at a time and needs scope to announce the correct header before each data cell.

scope accepts four meaningful values:

ValueThe header applies to…
colevery cell in the column below it
rowevery cell in the row to its right
colgroupa group of columns (used with <colgroup>)
rowgroupa group of rows (e.g. all rows inside one <tbody>)

A table can have headers in both directions. Column headers live in the <thead> with scope="col"; a row's leading label is a <th scope="row"> inside the <tbody>.

Example of a fully accessible table using scope

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      table {
        border-collapse: collapse;
        margin: 30px auto;
      }
      th,
      td {
        padding: 10px;
        border: 1px solid #666;
        text-align: left;
      }
      thead th,
      tbody th {
        background-color: #1c87c9;
        color: #fff;
      }
    </style>
  </head>
  <body>
    <table>
      <caption>Weekly study plan</caption>
      <thead>
        <tr>
          <th scope="col">Day</th>
          <th scope="col">Topic</th>
          <th scope="col">Hours</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th scope="row">Monday</th>
          <td>HTML</td>
          <td>2</td>
        </tr>
        <tr>
          <th scope="row">Tuesday</th>
          <td>CSS</td>
          <td>3</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

When a screen-reader user lands on the cell containing 3, it can announce "Tuesday, Hours, 3" because the column header (scope="col") and the row header (scope="row") are both unambiguous.

Accessibility

Why scope matters

A data table is a grid of relationships: each <td> belongs to one or more headers. Sighted users read those relationships visually; screen-reader users do not. Marking header cells with <th> and giving them a correct scope is what lets assistive technology say the right header out loud as the user moves through the table. Without it, a complex table is just a stream of disconnected values.

<th> vs. <td role>

Always use a real <th> element for headers rather than styling a <td> to look bold. A <th> carries header semantics automatically; a plain <td> does not, no matter how it looks. Reaching for role="columnheader" or role="rowheader" on a <td> should be a last resort (for example, when you cannot change the markup). Native <th> with scope is simpler and better supported.

The id / headers pattern for complex tables

scope works well for simple grids, but it cannot express every relationship in tables with irregular spans or multiple header levels. For those, give each header an id and list the relevant header ids on each data cell via the headers attribute (space-separated). This explicitly ties every cell to its headers.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      table { border-collapse: collapse; margin: 30px auto; }
      th, td { padding: 10px; border: 1px solid #666; }
    </style>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <th id="name">Name</th>
          <th id="q1">Q1</th>
          <th id="q2">Q2</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th id="alice" headers="name">Alice</th>
          <td headers="alice q1">120</td>
          <td headers="alice q2">150</td>
        </tr>
        <tr>
          <th id="bob" headers="name">Bob</th>
          <td headers="bob q1">90</td>
          <td headers="bob q2">110</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

Now the cell with 150 is explicitly associated with both the Alice row header and the Q2 column header, so a screen reader can announce "Alice, Q2, 150" with no guesswork.

The abbr attribute

When a header's full text is long, the abbr attribute supplies a short version. Some speech browsers read this abbreviated form (instead of repeating the long heading) every time they announce a cell in that column, which makes navigating wide tables far less tedious.

<th scope="col" abbr="HDI">Human Development Index</th>

The visible text stays "Human Development Index", but a screen reader may announce each cell in that column as just "HDI".

Attributes

Only abbr, colspan, rowspan, headers, and scope are valid in HTML5. The rows marked Deprecated below are obsolete presentational attributes — do not use them; achieve the same result with CSS instead.

AttributeValueDescription
abbrtextDefines an abbreviated version of the content in a header cell. Some user agents, such as speech readers, may announce this short form instead of the full text.
colspannumberDefines the number of columns a cell should span. The value must be a positive integer. Default value is 1.
headersheader_idA space-separated list of header cell ids that describe this cell. Each value must match the id of a header cell. Used for complex tables.
rowspannumberThe number of rows a cell should span. The value must be a positive integer. Default is 1. Values above 65534 are clipped to 65534.
scopecol / colgroup / row / rowgroupDeclares which cells the header relates to. Essential for table accessibility.
alignleft / right / centerDeprecated. Aligned the content. Use CSS text-align instead.
axiscategory_nameDeprecated. Categorized cells with similar content.
backgroundurlDeprecated. Set a background image. Use CSS background instead.
bgcolorrgb(x,x,x) / #xxxxxx / colornameDeprecated. Set the background color. Use CSS background-color.
bordercolorcolorDeprecated. Set the border color. Use CSS border.
charcharacterDeprecated. Aligned content to a character (only with align="char").
charoffnumberDeprecated. Offset of the alignment character.
height% / pixelsDeprecated. Set the cell height. Use CSS height.
nowrapnowrapDeprecated. Prevented content wrapping. Use CSS white-space: nowrap.
sorted(various)Deprecated. Defined a column's sort direction.
valigntop / middle / bottom / baselineDeprecated. Vertical alignment. Use CSS vertical-align.
width% / pixelsDeprecated. Set the cell width. Use CSS width.

The <th> tag also supports the Global Attributes and the Event Attributes.

How to style an HTML <th> tag

th {
  background-color: #f2f2f2;
  color: #333;
  padding: 8px;
  border: 1px solid #ccc;
}

Practice

Practice
What is the primary purpose of the HTML th element?
What is the primary purpose of the HTML th element?
Was this page helpful?