Loading Developer Playground

Loading ...

Skip to main content
ARIA ATTRIBUTERelationship Attributes

aria-rowspan

Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid.

Value Type
Integer (≥1)
Used With
cell, columnheader, rowheader
Default
1 (no spanning)

Overview

The aria-rowspan attribute defines the number of rows spanned by a cell within a table, grid, or treegrid. It's the ARIA equivalent of the HTML rowspan attribute.

Use this attribute when building custom grid components with role="grid" or role="treegrid" that have cells spanning multiple rows. For native HTML tables, use the rowspan attribute instead.

The value must be a positive integer. A value of 1 (the default) means the cell occupies a single row.

Live Demo: Schedule with Spanning Events

Time
Event
Location
9:00 AM
Morning Workshop
aria-rowspan="2"
Room A
10:00 AM
11:00 AM
Coffee Break
Lobby
12:00 PM
Keynote Presentation
aria-rowspan="2"
Main Hall
1:00 PM

Events with aria-rowspan span multiple time slots. Screen readers announce the span, e.g., "Morning Workshop, spans 2 rows".

Code Examples

Basic Usage

<!-- aria-rowspan indicates rows spanned by a cell -->

<table role="grid" aria-rowcount="6">
  <thead>
    <tr aria-rowindex="1">
      <th>Region</th>
      <th>Q1</th>
      <th>Q2</th>
    </tr>
  </thead>
  <tbody>
    <tr aria-rowindex="2">
      <!-- Header spans rows 2-4 -->
      <th aria-rowspan="3" scope="rowgroup">North America</th>
      <td>$1.2M</td>
      <td>$1.4M</td>
    </tr>
    <tr aria-rowindex="3">
      <td>$800K</td>
      <td>$950K</td>
    </tr>
    <tr aria-rowindex="4">
      <td>$600K</td>
      <td>$720K</td>
    </tr>
    <tr aria-rowindex="5">
      <!-- Header spans rows 5-6 -->
      <th aria-rowspan="2" scope="rowgroup">Europe</th>
      <td>$900K</td>
      <td>$1.1M</td>
    </tr>
    <tr aria-rowindex="6">
      <td>$750K</td>
      <td>$850K</td>
    </tr>
  </tbody>
</table>

Grid with Spanning Cells

<!-- aria-rowspan in grid with spanning cells -->

<div role="grid" aria-rowcount="5" aria-label="Weekly schedule">
  <div role="row" aria-rowindex="1">
    <div role="columnheader">Time</div>
    <div role="columnheader">Event</div>
    <div role="columnheader">Room</div>
  </div>
  
  <div role="row" aria-rowindex="2">
    <div role="rowheader">9:00 AM</div>
    <!-- Event spans 2 rows (9:00-10:00) -->
    <div role="gridcell" aria-rowspan="2">
      Morning Workshop
    </div>
    <div role="gridcell" aria-rowspan="2">
      Room A
    </div>
  </div>
  
  <div role="row" aria-rowindex="3">
    <div role="rowheader">10:00 AM</div>
    <!-- Cells from row 2 continue here -->
  </div>
  
  <div role="row" aria-rowindex="4">
    <div role="rowheader">11:00 AM</div>
    <!-- Event spans 2 rows (11:00-12:00) -->
    <div role="gridcell" aria-rowspan="2">
      Keynote Speech
    </div>
    <div role="gridcell" aria-rowspan="2">
      Main Hall
    </div>
  </div>
  
  <div role="row" aria-rowindex="5">
    <div role="rowheader">12:00 PM</div>
  </div>
</div>

Combined with Colspan

<!-- Combining aria-rowspan with aria-colspan -->

<div role="grid" aria-rowcount="4" aria-colcount="4">
  <div role="row" aria-rowindex="1">
    <div role="columnheader" aria-colindex="1">Header 1</div>
    <div role="columnheader" aria-colindex="2">Header 2</div>
    <div role="columnheader" aria-colindex="3">Header 3</div>
    <div role="columnheader" aria-colindex="4">Header 4</div>
  </div>
  
  <div role="row" aria-rowindex="2">
    <!-- Cell spans 2 rows and 2 columns -->
    <div 
      role="gridcell" 
      aria-colindex="1" 
      aria-rowspan="2" 
      aria-colspan="2"
    >
      Large merged cell (2x2)
    </div>
    <div role="gridcell" aria-colindex="3">Normal cell</div>
    <div role="gridcell" aria-colindex="4">Normal cell</div>
  </div>
  
  <div role="row" aria-rowindex="3">
    <!-- Columns 1-2 occupied by spanning cell above -->
    <div role="gridcell" aria-colindex="3">Normal cell</div>
    <div role="gridcell" aria-colindex="4">Normal cell</div>
  </div>
</div>

React Component

// React grid component with rowspan support
import { useMemo } from 'react';

interface GridCell {
  content: React.ReactNode;
  rowspan?: number;
  colspan?: number;
  isHeader?: boolean;
}

interface GridRow {
  rowIndex: number;
  cells: (GridCell | null)[]; // null for cells covered by spans
}

interface AccessibleGridProps {
  rows: GridRow[];
  totalRows: number;
  totalCols: number;
  label: string;
}

function AccessibleGrid({ rows, totalRows, totalCols, label }: AccessibleGridProps) {
  return (
    <div
      role="grid"
      aria-rowcount={totalRows}
      aria-colcount={totalCols}
      aria-label={label}
    >
      {rows.map(row => (
        <div key={row.rowIndex} role="row" aria-rowindex={row.rowIndex}>
          {row.cells.map((cell, colIdx) => {
            if (!cell) return null; // Cell covered by span
            
            const cellRole = cell.isHeader ? 'rowheader' : 'gridcell';
            
            return (
              <div
                key={colIdx}
                role={cellRole}
                aria-colindex={colIdx + 1}
                aria-rowspan={cell.rowspan}
                aria-colspan={cell.colspan}
              >
                {cell.content}
              </div>
            );
          })}
        </div>
      ))}
    </div>
  );
}

// Usage: Schedule with spanning events
function ScheduleGrid() {
  const rows: GridRow[] = [
    {
      rowIndex: 1,
      cells: [
        { content: 'Time', isHeader: true },
        { content: 'Event', isHeader: true },
        { content: 'Location', isHeader: true },
      ]
    },
    {
      rowIndex: 2,
      cells: [
        { content: '9:00 AM', isHeader: true },
        { content: 'Workshop (2 hrs)', rowspan: 2 },
        { content: 'Room A', rowspan: 2 },
      ]
    },
    {
      rowIndex: 3,
      cells: [
        { content: '10:00 AM', isHeader: true },
        null, // Covered by rowspan
        null, // Covered by rowspan
      ]
    },
    {
      rowIndex: 4,
      cells: [
        { content: '11:00 AM', isHeader: true },
        { content: 'Lunch Break' },
        { content: 'Cafeteria' },
      ]
    },
  ];

  return (
    <AccessibleGrid
      rows={rows}
      totalRows={4}
      totalCols={3}
      label="Conference schedule"
    />
  );
}

Related Attributes

Specifications & Resources