(g) Row and column headers shall be identified for data tables.

(h) Markup shall be used to associate data cells and header cells for data tables that have two or more logical levels of row or column headers.

Why are these two provisions necessary?
Paragraphs (g) and (h) permit the use of tables, but require that the tables be coded according to the rules of the markup language being used for creating tables. Large tables of data can be difficult to interpret if a person is using a non-visual means of accessing the web. Users of screen readers can easily get "lost" inside a table because it may be impossible to associate a particular cell that a screen reader is reading with the corresponding column headings and row names.

Let's briefly review of a typical table. In this example, we are tracking the work schedule of three employees at the Bedrock General Store.
Rows are the horizontal cells of the table
Betty 9-5 10-6 8-47-3
Wilma 10-6 10-6 9-5 9-5
Fred 10-6 10-6 10-6 10-6
Columns are the vertical cells of the table
Betty 9-5 10-6 8-47-3
Wilma 10-6 10-6 9-5 9-5
Fred 10-6 10-6 10-6 10-6

Because screen readers read one cell at a time and it is difficult for the impaired user to get an overview of the table and its contents, it is imperative that table data cells are associated with column headers. Assistive technology allows users to navigate among table cells and access header and other table cell information. Unless marked-up properly, these tables will not provide the assistive technology with the appropriate information.

Section 1194.22 (g) and (h) state that when information is displayed in a table format, the information shall be laid out using appropriate table tags as opposed to using a preformatted table in association with the "<pre>" tag. Web authors are also required to use one of several methods to provide an association between a header and its related information.

How can HTML tables be made readable with assistive technology?

  1. The first step is to add column headers.

    Browser View HTML Code
      Spring Summer Autumn Winter
    Betty 9-5 10-6 8-47-3
    Wilma 10-6 10-6 9-5 9-5
    Fred 10-6 10-6 10-6 10-6

    <table border=1 cellspacing=0 cellpadding=3>
    <tr>
       <th>&nbsp;</th>
       <th>Spring</th>
       <th>Summer</th>
       <th>Autumn</th>
       <th>Winter</th>
    </tr>
    <tr>
       <td>Betty</td>
       <td>9-5</td>
       <td>10-6</td>
       <td>8-4</td>
       <td>7-3</td>
    </tr>
    <tr>
       <td>Wilma</td>
       <td>10-6</td>
       <td>10-6</td>
       <td>9-5</td>
       <td>9-5</td>
    </tr>
    <tr>
      <td>Fred</td>
       <td>10-6</td>
       <td>10-6</td>
       <td>10-6</td>
       <td>10-6</td>
    </tr>
    </table>

  2. A second method intoduces the use of the "Scope" attribute in tables. The "scope" attribute is one of the most effective ways of making HTML compliant with these requirements. It is also the simplest method to implement. The scope attribute works with some (but not all) assistive technology in tables that use "colspan" or "rowspan" attributes in table header or data cells.

    Using the Scope Attribute - The first row of each table should include column headings. Typically, these column headings are inserted in <TH> tags, although <TD> tags can also be used. These tags at the top of each column should include the following attribute:

    scope="col"
    By doing this simple step, the text in that cell becomes associated with every cell in that column. Unlike using other approaches (notably "id" and "headers") there is no need to include special attributes in each cell of the table. Similarly, the first column of every table should include information identifying information about each row in the table. Each of the cells in that first column are created by either <TH> or <TD> tags. Include the following attribute in these cells:
    scope="row"
    By simply adding this attribute, the text in that cell becomes associated with every cell in that row. While this technique dramatically improves the usability of a web page, using the scope attribute does not appear to interfere in any way with browsers that do not support the attribute.

    Browser View HTML Code
      Spring Summer Autumn Winter
    Betty 9-5 10-6 8-47-3
    Wilma 10-6 10-6 9-5 9-5
    Fred 10-6 10-6 10-6 10-6
    <table border=1 cellspacing=0 cellpadding=3>
    <tr>
       <th>&nbsp;</th>
       <th scope="col">Spring</th>
       <th scope="col">Summer</th>
       <th scope="col">Autumn</th>
       <th scope="col">Winter</th>
    </tr>
    <tr>
       <td scope="row">Betty</td>
       <td>9-5</td>
       <td>10-6</td>
       <td>8-4</td>
       <td>7-3</td>
    </tr>
    <tr>
       <td scope="row">Wilma</td>
       <td>10-6</td>
       <td>10-6</td>
       <td>9-5</td>
       <td>9-5</td>
    </tr>
    <tr>
       <td scope="row">Fred</td>
       <td>10-6</td>
       <td>10-6</td>
       <td>10-6</td>
       <td>10-6</td>
    </tr>

    The efficiency of using the scope attribute becomes more apparent in much larger tables. For instance, if your page used a table with 20 rows and 20 columns, there would be 400 data cells in the table. To make this table comply with this provision without using the scope attribute would require special coding in all 400 data cells, plus the 40 header and row cells. By contrast, using the scope attribute would only require special attributes in the 40 header and row cells.

  3. Using the "ID" and "Headers" Attributes in Tables
    Unlike using the "scope" attribute, using the "id" and "headers" attributes requires that every data cell in a table include special attributes for association. Although its usefulness for accessibility may have been diminished as browsers provide support for the "scope" attribute, the "id" and "headers" attributes are still very useful and provide a practical means of providing access in smaller tables.

    The table in this example includes the work schedules for two employees. Each employee has a morning and afternoon work schedule that varies depending on whether the employee is working in the winter or summer months. The "summer" and "winter" columns each span two columns labeled "morning" and "afternoon." Therefore, in each cell identifying the work schedule, the user needs to be told the employee's name (Fred or Wilma), the season (Summer or Winter), and the shift (morning or afternoon).

      Winter Summer
      Morning Afternoon Morning Afternoon
    Wilma 9-11 12-6 7-11 12-3
    Fred 10-11 12-6 9-11 12-5

    This table is much more complicated than the previous example and demonstrates the use of the "id" and "headers" attributes on the left side of the page and then the scope attribute on the right side. Both methods provide a means of complying with the requirements for data tables in web pages.

    ID & Header Example Scope Example
    <table border=1 cellspacing=0 cellpadding=3>
    <tr>
       <th>&nbsp;</th>
       <th colspan="2" id="winter">Winter</th>
       <th colspan="2" id="summer">Summer</th>
    </tr>
    <tr>
       <th>&nbsp;</th>
       <th id="am1">Morning</th>
       <th id="pm1">Afternoon</th>
       <th id="am2">Morning</th>
       <th id="pm2">Afternoon</th>
    </tr>
    <tr>
       <td id="wilma">Wilma</td>
       <td headers="wilma am1 winter">9-11</td>
       <td headers="wilma pm1 winter">12-6</td>
       <td headers="wilma am2 summer">7-11</td>
       <td headers="wilma pm2 summer">12-3</td>
    </tr>
    <tr>
       <td id="fred">Fred</td>
       <td headers="fred am1 winter">10-11</td>
       <td headers="fred pm1 winter">12-6</td>
       <td headers="fred am2 summer">9-11</td>
       <td headers="fred pm2 summer">12-5</td>
    </tr>
    </table>
    <table cellspacing=0 cellpadding=3>
    <tr>
       <th>&nbsp;</th>
       <th colspan="2" scope="col">Winter</th>
       <th colspan="2" scope="col">Summer</th>
    </tr>
    <tr>
       <th>&nbsp;</th>
       <th scope="col">Morning</th>
       <th scope="col">Afternoon</th>
       <th scope="col">Morning</th>
       <th scope="col">Afternoon</th>
    </tr>
    <tr>
       <td scope="row">Wilma</td>
       <td>9-11</td>
       <td>12-6</td>
       <td>7-11</td>
       <td>12-3</td>
    </tr>
    <tr>
       <td scope="row">Fred</td>
       <td>10-11</td>
       <td>12-6</td>
       <td>9-11</td>
       <td>12-5</td>
    </tr>
    </table>

Is the summary attribute an option?
Although highly recommended by some webpage designers as a way of summarizing the contents of a table, the "summary" attribute of the TABLE tag is not sufficiently supported by major assistive technology manufacturers to warrant recommendation. Therefore, web developers who are interested in summarizing their tables should consider placing their descriptions either adjacent to their tables or in the body of the table, using such tags as the CAPTION tag. In no event should web developers use summarizing tables as an alternative to making the contents of their tables compliant as described above.


Link to previous page.
Previous Slide
Link to elements page.
First Slide
Link to next page.
Next Slide