Loading Developer Playground

Loading ...

Skip to main content
ARIA ATTRIBUTERelationship Attributes

aria-colindex

Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid.

Value Type
Integer (≥1)
Used With
cell, row, columnheader, rowheader
Index
1-based (starts at 1)

Overview

The aria-colindex attribute defines an element's column index or position within a table, grid, or treegrid. The value is an integer greater than or equal to 1, representing the column position.

This attribute is essential when implementing virtual scrolling or displaying a subset of columns. It tells assistive technologies the true position of each visible cell within the complete grid structure.

When used on a row element, aria-colindex defines the column index of the first cell in that row, and child cells inherit sequential indices.

Live Demo: Virtual Column Scrolling

Showing columns 1-4 of 10:
Acolindex: 1Bcolindex: 2Ccolindex: 3Dcolindex: 4
A1B1C1D1
A2B2C2D2
A3B3C3D3

Each cell has aria-colindex indicating its true column position. Screen readers announce "Column 1 of 10" for the first visible cell, helping users understand their position in the full grid.

Code Examples

Basic Usage

<!-- aria-colindex indicates a cell's column position -->

<!-- Sparse table showing columns 1, 2, 5, and 8 of 10 -->
<table role="grid" aria-colcount="10" aria-label="Sales data">
  <thead>
    <tr>
      <th aria-colindex="1">ID</th>
      <th aria-colindex="2">Product</th>
      <th aria-colindex="5">Price</th>
      <th aria-colindex="8">Stock</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td aria-colindex="1">001</td>
      <td aria-colindex="2">Widget</td>
      <td aria-colindex="5">$29.99</td>
      <td aria-colindex="8">150</td>
    </tr>
  </tbody>
</table>

<!-- Screen reader: "Column 5 of 10, Price" -->

Grid with Navigation

<!-- Grid with keyboard navigation using aria-colindex -->

<div 
  role="grid" 
  aria-colcount="100"
  aria-label="Spreadsheet"
  tabindex="0"
>
  <div role="row" aria-rowindex="1">
    <!-- Only columns 25-30 visible in viewport -->
    <div role="columnheader" aria-colindex="25">Y</div>
    <div role="columnheader" aria-colindex="26">Z</div>
    <div role="columnheader" aria-colindex="27">AA</div>
    <div role="columnheader" aria-colindex="28">AB</div>
    <div role="columnheader" aria-colindex="29">AC</div>
    <div role="columnheader" aria-colindex="30">AD</div>
  </div>
  
  <div role="row" aria-rowindex="2">
    <div role="gridcell" aria-colindex="25" tabindex="-1">Y2</div>
    <div role="gridcell" aria-colindex="26" tabindex="-1">Z2</div>
    <div role="gridcell" aria-colindex="27" tabindex="-1">AA2</div>
    <div role="gridcell" aria-colindex="28" tabindex="-1">AB2</div>
    <div role="gridcell" aria-colindex="29" tabindex="-1">AC2</div>
    <div role="gridcell" aria-colindex="30" tabindex="-1">AD2</div>
  </div>
</div>

With Column Spanning

<!-- aria-colindex with spanning cells -->

<table role="grid" aria-colcount="6">
  <thead>
    <tr>
      <!-- Header spans columns 1-2 -->
      <th aria-colindex="1" aria-colspan="2">Name</th>
      <!-- Header at column 3 -->
      <th aria-colindex="3">Age</th>
      <!-- Header spans columns 4-6 -->
      <th aria-colindex="4" aria-colspan="3">Contact Info</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td aria-colindex="1">First</td>
      <td aria-colindex="2">Last</td>
      <td aria-colindex="3">32</td>
      <td aria-colindex="4">Email</td>
      <td aria-colindex="5">Phone</td>
      <td aria-colindex="6">Address</td>
    </tr>
  </tbody>
</table>

React Component

// React component with aria-colindex for virtual columns
import { useState, useCallback } from 'react';

interface VirtualGridProps {
  totalColumns: number;
  totalRows: number;
  visibleColumnCount: number;
  getCellValue: (row: number, col: number) => string;
}

function VirtualGrid({
  totalColumns,
  totalRows,
  visibleColumnCount,
  getCellValue
}: VirtualGridProps) {
  const [startCol, setStartCol] = useState(1);
  const [focusedCell, setFocusedCell] = useState({ row: 1, col: 1 });
  
  const visibleColumns = Array.from(
    { length: visibleColumnCount },
    (_, i) => startCol + i
  ).filter(col => col <= totalColumns);

  const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
    const { row, col } = focusedCell;
    
    switch (e.key) {
      case 'ArrowRight':
        if (col < totalColumns) {
          const newCol = col + 1;
          setFocusedCell({ row, col: newCol });
          // Scroll viewport if needed
          if (newCol >= startCol + visibleColumnCount) {
            setStartCol(newCol - visibleColumnCount + 1);
          }
        }
        e.preventDefault();
        break;
      case 'ArrowLeft':
        if (col > 1) {
          const newCol = col - 1;
          setFocusedCell({ row, col: newCol });
          if (newCol < startCol) {
            setStartCol(newCol);
          }
        }
        e.preventDefault();
        break;
      // ... handle up/down for rows
    }
  }, [focusedCell, startCol, totalColumns, visibleColumnCount]);

  return (
    <div
      role="grid"
      aria-colcount={totalColumns}
      aria-rowcount={totalRows}
      aria-label="Data grid"
      onKeyDown={handleKeyDown}
    >
      <div role="row" aria-rowindex={1}>
        {visibleColumns.map(col => (
          <div
            key={col}
            role="columnheader"
            aria-colindex={col}
          >
            Column {col}
          </div>
        ))}
      </div>
      
      {Array.from({ length: 5 }, (_, rowIdx) => (
        <div key={rowIdx + 2} role="row" aria-rowindex={rowIdx + 2}>
          {visibleColumns.map(col => (
            <div
              key={col}
              role="gridcell"
              aria-colindex={col}
              tabIndex={
                focusedCell.row === rowIdx + 2 && focusedCell.col === col 
                  ? 0 : -1
              }
            >
              {getCellValue(rowIdx + 2, col)}
            </div>
          ))}
        </div>
      ))}
    </div>
  );
}

Related Attributes

Specifications & Resources