References

Beginner-friendly references for web development, with live, editable examples.

The HTML aria-rowindextext attribute

ARIA Accessibility
In short

Where a row's number isn't what people see, aria-rowindextext supplies the label, such as rank 8 in chess. WAI-ARIA 1.3, still a draft, is the first version to define it. In that draft, each row should carry it, and its cells may.

Overview

The aria-rowindextext attribute holds a readable label that stands in for a row's aria-rowindex number. On a chess board seen from White's side, the top row is rank 8 even though it's the first row in the DOM, so aria-rowindex="1" and aria-rowindextext="8" describe the same row.

It's defined in WAI-ARIA 1.3, whose latest published text is a draft dated June 4, 2026, so don't expect it in version 1.2, the W3C Recommendation.

Placement is more generous than for aria-colindextext, which the row role doesn't support. Each row should carry this one, the draft says, and all of that row's cells may carry it too.

Firefox exposes the text on whichever element carries it, row or cell. In Chrome on Windows, a value on a row doesn't reach the platform accessibility APIs, while the same value on a cell does, so set it in both places.

Reserve it for rows whose number misleads. The draft's test is an aria-rowindex that "is not meaningful" or doesn't match the displayed index, as in the game Battleship. A chess board is another case.

Syntax

<div role="grid" aria-label="Chess board">
  <div role="row" aria-rowindex="1" aria-rowindextext="8">
    <span role="gridcell" aria-rowindex="1"
          aria-rowindextext="8">Rook</span>
  </div>
</div>

Values

Value
A string.

Example

Live example
<p style="margin: 0 0 6px">Flip the board. The aria-rowindex values stay, and the rank text changes.</p>
<div style="display: flex; gap: 10px; align-items: flex-start">
  <table aria-label="Chess board" style="border-collapse: collapse; font: 12px/18px monospace">
    <tbody id="board"></tbody>
  </table>
  <div style="flex: 1; min-width: 0">
    <button id="flip">Flip board</button>
    <p role="status" id="state" style="margin: 6px 0 0; font-size: 13px"></p>
  </div>
</div>
<script>
const start = {
  8: 'rnbqkbnr',
  7: 'pppppppp',
  2: 'PPPPPPPP',
  1: 'RNBQKBNR'
};
const board = document.getElementById('board');
const state = document.getElementById('state');
let white = true;

function square(row, tag, text, position, rank) {
  const cell = document.createElement(tag);
  cell.textContent = text;
  cell.setAttribute('aria-rowindex', position);
  cell.setAttribute('aria-rowindextext', rank);
  cell.style.width = '18px';
  cell.style.textAlign = 'center';
  cell.style.padding = '0';
  row.appendChild(cell);
  return cell;
}

function render() {
  board.replaceChildren();
  for (let position = 1; position <= 8; position++) {
    const rank = white ? 9 - position : position;
    const pieces = start[rank] || '        ';
    const row = board.insertRow();
    row.setAttribute('aria-rowindex', position);
    row.setAttribute('aria-rowindextext', rank);
    square(row, 'th', rank, position, rank).scope = 'row';
    for (let file = 0; file < 8; file++) {
      const piece = pieces[white ? file : 7 - file];
      const cell = square(row, 'td', piece.trim(), position, rank);
      cell.style.background = (position + file) % 2 ? '#eef2f6' : '#c9d6e3';
      cell.style.color = '#10202f';
    }
  }
  const top = board.rows[0];
  state.textContent = 'Top row: aria-rowindex ' + top.getAttribute('aria-rowindex') + ', aria-rowindextext ' + top.getAttribute('aria-rowindextext') + '. White is at the ' + (white ? 'bottom.' : 'top.');
}

document.getElementById('flip').addEventListener('click', () => {
  white = !white;
  render();
});
render();
</script>

Best practices

  • Keep aria-rowindextext next to the number, not in its place. Position tracking and table navigation in some assistive technologies depend on the numeric index.
  • Repeat the text on a row's header cell as well as its data cells. In the draft, the rowheader role inherits the attribute from cell.
  • Update the text in the same step that changes the display, as when a board flips or a sheet shifts its labels.
  • Set the text on a <tr> and on its cells when the table is native, since a tr counts as a row for this attribute.

Frequently asked questions

Can you rely on aria-rowindextext while it's still a draft?
Treat aria-rowindextext as a draft feature with aria-rowindex as the fallback. The matching ariaRowIndexText property arrived in Chrome 128, Firefox 119 and Safari 26.2, but that says nothing about assistive technology support.
Should a chess board use aria-rowindextext or a rowheader cell?
A chess board can use aria-rowindextext and a rowheader cell together. The rowheader names the row's contents, while the attribute stands in for its position number.
Does aria-rowindextext change when a board flips?
Yes, aria-rowindextext should follow what's displayed, so the top row reads 1 after a flip. The aria-rowindex of that row stays 1 either way, because it counts rows from the top of the table.
Does a chess board with aria-rowindextext also set aria-rowcount?
No, a chess board keeps its 8 rows in the DOM, so aria-rowindextext works there without aria-rowcount.
Can aria-rowindextext be used without aria-rowindex?
Yes, aria-rowindextext's rule in the 1.3 draft covers a calculated row index as well as a provided one. Still, keep it alongside aria-rowindex.