ARIA table examples

Example 1

This example uses a range of roles to define table structure.

Animals found in different habitats

Habitat Mammal Bird Reptile
Forest Deer Owl Lizard
Ocean Dolphin Albatross Turtle
Desert Camel Falcon Gecko
Wetland Otter Heron Crocodile
HTML markup
<h3 id="aaa">Animals found in different habitats</h3>
<div role="table" aria-labelledby="aaa">
  <div role="rowgroup">
    <div role="row">
      <span role="columnheader">Habitat</span>
      <span role="columnheader">Mammal</span>
      <span role="columnheader">Bird</span>
      <span role="columnheader">Reptile</span>
    </div>
  </div>

  <div role="rowgroup">
    <div role="row">
      <span role="rowheader">Forest</span>
      <span role="cell">Deer</span>
      <span role="cell">Owl</span>
      <span role="cell">Lizard</span>
    </div>
    <div role="row">
      <span role="rowheader">Ocean</span>
      <span role="cell">Dolphin</span>
      <span role="cell">Albatross</span>
      <span role="cell">Turtle</span>
    </div>
    <div role="row">
      <span role="rowheader">Desert</span>
      <span role="cell">Camel</span>
      <span role="cell">Falcon</span>
      <span role="cell">Gecko</span>
    </div>
    <div role="row">
      <span role="rowheader">Wetland</span>
      <span role="cell">Otter</span>
      <span role="cell">Heron</span>
      <span role="cell">Crocodile</span>
    </div>
  </div>
</div>

Example 2: Sortable table (role="grid")

This example uses role="grid" instead of role="table", since the columns can be sorted, an interactive behaviour static tables don't have. Activate a column header to sort by that column. aria-sort is updated on the active columnheader to reflect the current sort direction.

Note: a fully spec-complete grid also supports arrow-key navigation between individual cells. That behaviour is not implemented in this simplified example, keyboard interaction here is limited to activating the sort buttons in the header row.

Species count and average temperature by habitat

Forest 120 12
Ocean 230 17
Desert 45 38
Wetland 88 22
HTML markup
<h3 id="bbb">Species count...</h3>

<div id="sort-announcer" class="hidden" role="status"></div>

<div role="grid" aria-labelledby="bbb" id="sortable-grid">
  <div role="rowgroup">
    <div role="row">
      <span
        role="columnheader"
        aria-sort="none"
        data-column="habitat"
        data-type="text"
      >
        <button aria-label="Habitat - activate to sort">
          Habitat
          <span aria-hidden="true"></span>
        </button>
      </span>
      <span
        role="columnheader" 
        aria-sort="none" 
        data-column="species" 
        data-type="number"
      >
        <button aria-label="Number of species - activate to sort">
          Number of species 
          <span aria-hidden="true"></span>
        </button>
      </span>
      <span 
        role="columnheader" 
        aria-sort="none" 
        data-column="temperature" 
        data-type="number"
      >
        <button aria-label="Average temp - activate to sort">
          Average temp
          <span aria-hidden="true"></span>
        </button>
      </span>
    </div>
  </div>
  <div role="rowgroup" id="sortable-grid-body">
    <div role="row">
      <span role="rowheader">Forest</span>
      <span role="gridcell">120</span>
      <span role="gridcell">12</span>
    </div>

    <!-- remaining rows follow the same pattern -->
  </div>
</div>

Features demonstrated in this example

Why this example uses an ARIA grid instead of a native <table>

A native <table> provides built-in structure, relationships and behaviour. This makes it the best choice for displaying static tabular data. However, once a table becomes highly interactive, such as supporting sortable columns, developers often need greater control over its behaviour and presentation.

An ARIA grid is built from generic elements, such as <div> and <span>, with ARIA roles providing the semantics. This makes it easier to add interactive features such as sorting, update states like aria-sort, and reorder rows using JavaScript without working against native table behaviour.

The trade-off is that none of the accessibility provided by a native table comes for free. Developers must correctly recreate the table structure, relationships and states using ARIA. While ARIA grids offer greater flexibility, they also require much more care to implement and test correctly.