Lattice Grid Buy a licence

demo D117

Screen reader

What the grid announces, and the ARIA it writes

aria-rowindex · aria-selected

Building…
Loading a live grid…

The configuration

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.css">
<script src="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.13.0/lattice-grid.min.js"></script>

<div id="grid" style="height: 540px"></div>

<script>
  const grid = LatticeGrid.createGrid(document.getElementById('grid'), {
    rowKey: 'id',
    selection: 'multiple',
    columns: [
      { field: 'service', title: 'Service', layout: { width: 150 } },
      { field: 'team', title: 'Team', filter: { type: 'set' } },
      { field: 'state', title: 'State' },
      { field: 'instances', title: 'Instances', type: 'number' },
      { field: 'uptime', title: 'Uptime', type: 'number', format: { style: 'percent', decimals: 3 } },
    ],
    rows,  // 2,000 service records
  });

  // Select through the API so aria-selected is true on those rows for
  // assistive technology.
  const keys = [1, 2].map((i) => grid.rows.get(i)?.key).filter(Boolean);
  if (keys.length) grid.selection.set(keys);
</script>

What a screen reader hears when it lands on a grid

A JavaScript data grid that virtualises its rows presents a problem no static table has: the DOM only contains the cells currently on screen, so a screen reader’s row and column counts have to come from attributes, not from counting children. Lattice Grid writes aria-rowindex and aria-colindex on every rendered cell against the full logical size of the data, not the rendered window, so a user hears “row 4,208 of 1,000,000” even though row 4,208 is the only one of those in the DOM at that moment. Selection state is exposed the same way: aria-selected tracks the grid’s own selection model on the row and, where relevant, the cell, so a checkbox column and a screen reader announcement never drift apart. A developer reaches for this when a procurement checklist names WCAG or Section 508, or when support tickets show a user navigating with NVDA, JAWS or VoiceOver rather than a mouse. The grid role structure follows the ARIA grid pattern, with aria-rowcount and aria-colcount set on the container so assistive technology can announce position without walking the whole dataset, and it holds regardless of column virtualisation, so a wide grid with two hundred columns still reports the same indices for the ones currently off-screen.

Does a virtualised JavaScript data grid work with a screen reader?

It can, provided the rows and columns still on screen carry position information about the full dataset, not just the rendered subset. Lattice Grid sets aria-rowindex, aria-colindex, aria-rowcount and aria-colcount from the logical grid size, and keeps aria-selected in step with its selection model, so announcements stay correct as the DOM recycles during scrolling.