Irregular headers

Designing with irregular headers

A table is irregular when one or more of its headers span multiple columns or rows.

HTML introduces attributes and elements dedicated to representing the relationships between these row- or column-spanning headers and the data cells they define.

The scope attribute

When a header spans multiple columns, add the scope="colgroup" attribute to the <th> element. See header A in the example table below.

When a header spans multiple rows, add the scope="rowgroup" attribute to the <th> element. See header B in the example table below.

For solo column headers, add the scope="col" attribute to the <th> element. See headers A1, A2, A3 in the example table below.

For solo row headers, add the scope="row" attribute to the <th> element. See headers B1, B2 in the example table below.

Table with a column-spanning header and a row-spanning header
  A
A1 A2 A3
B B1      
B2      

Screen reader support for the scope="rowgroup" attribute is worse than support for scope="colgroup". When possible, design tables to leverage scope="colgroup" and avoid scope="rowgroup".

View HTML
<table class="table table-bordered">
   <caption>Table with a column-spanning header and a row-spanning header</caption>
   <thead class="bg-primary">
      <tr>
        <td colspan="2" rowspan="2">&nbsp;</td>
        <th colspan="3" scope="colgroup">A</th>
      </tr>
      <tr>
        <th scope="col">A1</th>
        <th scope="col">A2</th>
        <th scope="col">A3</th>
      </tr>
   </thead>
   <tbody>
      <tr>
        <th rowspan="2" class="bg-primary" scope="rowgroup">B</th>
        <th class="bg-primary" scope="row">B1</th>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <th class="bg-primary" scope="row">B2</th>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
   </tbody>
</table>

The group-defining elements

Irregular tables also define their solo columns and spanning columns with the <col> and <colgroup> elements, respectively. These elements are the first children of the table element and are listed in the order the columns appear in the table. The span attribute of the <colgroup> element holds the number of columns spanned.

Irregular tables define row groups using the <thead>, <tbody> and <tfoot> elements. <tbody> defines a new row group of rows with each use, while <thead> and <tfoot> do as well but can only be used once per table.

  Good example: Table with column and row-spanning headers

In this example, "Country" and "Onwership" are solo columns, each identified with a <col> element. "Scenario" spans columns, identified with a <colgroup span="3"> element. The "Canada" and "USA" headers and their respective rows are each nested in a <tbody> element.

Ownership scenarios, Canada vs USA
Country Ownership Scenario
A B C
Canada Purchase likely very unlikely n/a
Rent unlikely very unlikely very unlikely
USA Purchase unlikely very unlikely very unlikely
Rent likely very likely n/a
View HTML
<table class="table table-bordered">
   <col> 
   <col> 
   <colgroup span="3"></colgroup> 
   <caption>Ownership scenarios, Canada vs USA</caption> 	          
   <thead> 
      <tr class="bg-success"> 
         <th scope="col" rowspan="2">Country</th> 
         <th scope="col" rowspan="2">Ownership</th> 
         <th scope="colgroup" colspan="3">Scenario</th> 
      </tr> 
      <tr class="bg-success"> 
         <th scope="col">A</th> 
         <th scope="col">B</th> 
         <th scope="col">C</th> 
      </tr>    
   </thead> 
   <tbody> 
      <tr> 
         <th scope="rowgroup" rowspan="2" class="bg-success">Canada</th> 
         <th scope="row" class="bg-success">Purchase</th> 
         <td>likely</td> 
         <td>very unlikely</td> 
         <td>n/a</td> 
      </tr> 
      <tr> 
         <th scope="row" class="bg-success">Rent</th> 
         <td>unlikely</td> 
         <td>very unlikely</td> 
         <td>very unlikely</td> 
      </tr> 
   </tbody> 
   <tbody> 
      <tr> 
         <th scope="rowgroup" rowspan="2" class="bg-success">USA</th> 
         <th scope="row" class="bg-success">Purchase</th> 
         <td>unlikely</td> 
         <td>very unlikely</td> 
         <td>very unlikely</td> 
      </tr> 
      <tr> 
         <th scope="row" class="bg-success">Rent</th> 
         <td>likely</td> 
         <td>very likely</td> 
         <td>n/a</td> 
      </tr> 
   </tbody> 
</table>

Related WCAG resources

Related WCAG resources

Success criteria

Techniques

Back to top