Skip to main content

Accessibility in DHTMLX Grid

DHTMLX Grid is built to be operated entirely from the keyboard and to expose its structure and state to assistive technology. WAI-ARIA semantics are part of the rendered markup, and a single, coherent focus model spans the header, body, and footer. The semantics are always present — there is no configuration flag to disable them.

Capabilities

AreaSupport
Keyboard operationFull: cell navigation, editing, sorting, range selection, tree expand/collapse, and clipboard all have keyboard equivalents
WAI-ARIA semanticsBuilt-in (grid / treegrid model), enabled always — no opt-in flag
Focus modelA single tab stop per zone; focus moves between header, body, and footer
Selection modelTwo modes: single-cell/row (selection) and spreadsheet-style range (blockSelection)
High-contrast displayLight and dark high-contrast themes (contrast-light / contrast-dark)

Covered areas

This documentation covers the Grid widget:

  • the data body — cells and rows, including tree mode (type: "tree")
  • the column header — sortable headers and in-header filters
  • the footer — summaries and footer filters
  • the inline editors
  • the keyboard model that connects these zones.

As with any embeddable component, the accessibility of the final page also depends on the host application (see Host-page responsibilities).

WAI-ARIA support

WAI-ARIA roles and attributes are added to the component markup automatically and are on by default — there is no flag to turn them off. The Grid exposes itself to assistive technology as an interactive grid (or treegrid) of rows and cells, with a separate group for the header and footer. The semantics are applied per structural part of the widget, so each part is announced with the correct role and state.

Grid container

The following table lists the container role and the grid-wide attributes applied to the root grid element, which describe the grid as a whole:

SelectorRole / attributePurpose
.dhx_gridrole="grid"Standard grid
.dhx_gridrole="treegrid"TreeGrid (type: "tree")
.dhx_gridaria-rowcountTotal number of data rows
.dhx_gridaria-colcountNumber of visible columns
.dhx_gridaria-readonly"true" when the grid is not editable
.dhx_gridaria-multiselectable"true" when multi-selection is enabled

Rows and cells

The following table lists the roles and the position and state attributes applied to data rows and cells, which let assistive technology announce where the user is:

SelectorRole / attributePurpose
Data rowrole="row"A row of the grid
Data rowaria-rowindex1-based row position
Data cellrole="gridcell"A data cell
Data cellaria-colindex1-based column position
Data cellaria-readonly"true" when the cell is not editable
Data cellaria-selectedSelection state of the cell

Tree (TreeGrid) rows

The following table lists the hierarchy attributes applied to tree rows and the role on the expand/collapse toggle in TreeGrid mode (type: "tree"), which convey the row's depth and open/closed state:

SelectorRole / attributePurpose
Tree rowaria-levelDepth of the row in the hierarchy
Tree rowaria-expandedOpen/closed state of a branch with children
Tree rowaria-selectedSelection state of the row
Expand/collapse togglerole="button" + aria-label"Expand group" / "Collapse group"

The following table lists the roles and attributes applied to the header and footer groups, rows, and cells, which expose the column headers, sort state, and filter controls:

SelectorRole / attributePurpose
Header/footer grouprole="rowgroup" + aria-rowcountGroups the header or footer rows
Header/footer rowrole="row" + aria-rowindexA header or footer row
Header cellrole="columnheader" + aria-sortColumn header; aria-sort is none / ascending / descending
Footer cellrole="gridcell" + aria-colindexA footer (summary) cell
Content (filter) cellrole="gridcell"Header/footer cell hosting a filter control
Sort affordancerole="button" + aria-label="Sort by …"Keyboard- and pointer-activatable sort trigger

Editors and filters

In-place editor inputs and header/footer filters receive an accessible name derived from column header text, so screen-reader users hear which column they are editing or filtering. For example, a filter input is labeled "Filter {column}" and a date filter "Filter by date: {column}".

Hidden and decorative elements

Resizer grips, sort icons, sort-order counters, drag ghosts, drop indicators, and the selection overlay are removed from the accessibility tree with aria-hidden="true" / role="presentation", so screen readers are not cluttered with redundant markup.

Selection modes

The keyboard behavior of the body depends on which selection system is enabled. The two are independent and drive different ARIA output and shortcut semantics.

1. Cell / row selection — selection

A single active cell (or row) moves with the arrow keys. This populates aria-selected on the focused cell or row. Extending the selection with Shift is enabled only when multiselection: true; without it, Shift+arrow moves the active cell.

// Single active cell, navigable with arrows / Tab / Home / End / Page Up·Down
const grid = new dhx.Grid("grid_container", {
columns: [/* ... */],
data: dataset,
selection: "complex", // "cell" | "row" | "complex"
multiselection: true, // enables Shift+Arrow multi-select
keyNavigation: true // default
});
selection valueMeaning
"cell"One active cell; Shift+arrow extends when multiselection: true
"row"One active row; arrows move the whole row, aria-selected is on the row
"complex"Cell- and row-style selection combined
trueEquivalent to cell selection
falsy / unsetSelection (and aria-selected) disabled

2. Range / block selection — blockSelection

Spreadsheet-style rectangular ranges. The arrow keys move the range anchor; Shift+arrows grow or shrink the rectangle; Delete clears the range (when editing is enabled). This applies in "range" mode.

// Google-Sheets-style range selection
const grid = new dhx.Grid("grid_container", {
columns: [/* ... */],
data: dataset,
blockSelection: true, // range mode (Shift+Arrow grows the rectangle)
editable: true, // allows Delete to clear the range
keyNavigation: true
});
blockSelection valueModeKeyboard effect
truerangeArrows move the range; Shift+arrows extend the rectangle; Delete clears it

Both systems coexist with the same navigation keys; the Grid responds to whichever selection system is active.

Keyboard navigation

Keyboard navigation is on by default (keyNavigation: true); set keyNavigation: false to opt out. Focus enters the Grid through hidden focus sentinels placed before the header and after the footer, which direct it into the correct zone. Within each zone a single cell is the tab stop, and the arrow keys move between cells from there.

Shortcuts are organized into zones — body, header, footer — and resolved by where focus currently is. The full reference is in the Keyboard navigation article; the tables below summarize it.

Grid body

KeysActionSelection mode
/ / / Move the selected cell one row/column ( from the first row enters the header; from the last row enters the footer when a footer exists)both
Ctrl + arrowJump the selection to the first/last cell in that directionboth
Shift + arrowExtend the selection by one cellselection with multiselection: true, or blockSelection range
Ctrl + Shift + arrowExtend the selection to the edgeas above
Home / EndMove to the first / last column of the current rowboth
Ctrl + Home / Ctrl + EndMove to the first / last cell of the gridboth
Shift + Home / End, Ctrl + Shift + Home / EndExtend the selection to the row/grid extentextend-capable modes
Page Up / Page DownMove the selected cell up / down by one page of visible rowsboth
Shift + Page Up / Page DownExtend the selection by one pageextend-capable modes
EnterOpen the editor (or toggle a boolean cell); when editing, commit and closerequires editable
F2Open the editor of the selected cell (non-boolean)requires editable
SpaceToggle a boolean cellrequires editable
EscapeCancel editing without savingrequires editable
Tab / Shift + TabMove to the next / previous cell, wrapping rows; exits to the footer / header at the endsboth
DeleteClear the selected rangeblockSelection range mode + editable
Ctrl + Z / Ctrl + Shift + ZUndo / RedoHistory module
Ctrl + EnterExpand / collapse the row (type: "tree")TreeGrid
/ (tree column)Expand / collapse a branch, or move to first child / parentTreeGrid
KeysAction
/ Move between header cells (colspan-aware)
/ Move between header rows (multi-row header); from the first row has no effect, from the last row moves into the body
Enter / SpaceSort by the column; on a filter cell, Enter activates the filter control
Shift + EnterToggle multi-sort for the column (requires multiSort)
Tab / Shift + TabMove within the header with row wrapping; exits to the body / out of the grid at the ends
EscapeDeactivate a filter control (restoring focus to its cell), or return focus to the body
KeysAction
/ Move between footer cells (colspan-aware)
/ Move between footer rows (multi-row footer); from the first row moves into the body, from the last row has no effect
EnterActivate a footer filter control
Tab / Shift + TabMove within the footer with row wrapping; exits the grid / to the body at the ends
EscapeDeactivate a filter control, or return focus to the body
note

Navigation is span-aware: movement across merged (colspan/rowspan) header and footer cells stays predictable, and the logical navigation row is preserved. When focus reaches an off-screen (virtualized) column, the Grid scrolls it into view automatically.

Assistive technology

What the Grid exposes to assistive technology is driven entirely by the ARIA markup above. Rows and cells carry their position (aria-rowindex / aria-colindex) against the grid totals (aria-rowcount / aria-colcount), so position is announced even when rows are virtualized. Selection is exposed through aria-selected, editability through aria-readonly, sort state through aria-sort, and — in tree mode (type: "tree") — hierarchy through aria-level and aria-expanded.

High contrast and focus

  • High-contrast themes. Light and dark high-contrast themes ship with the library (contrast-light and contrast-dark), activated by setting data-dhx-theme="contrast-light" or data-dhx-theme="contrast-dark". See the Themes guide and the Light High Contrast / Dark High Contrast pages for details.
  • Visible focus. Focus is tracked per zone by the roving-tabindex model, so the active cell is the single tab stop and moves predictably with the arrow keys.

Configuration recipes

// A. Cell navigation (single active cell)
new dhx.Grid("grid_container", {
columns, data,
selection: "complex",
multiselection: true, // Shift+Arrow multi-select
keyNavigation: true, // default
sortable: true // default — keyboard sort in headers
});

// B. Spreadsheet-style range selection
new dhx.Grid("grid_container", {
columns, data,
blockSelection: true, // range mode: Shift+Arrow grows the rectangle, Delete clears
editable: true
});

// C. TreeGrid (adds role="treegrid", aria-level, aria-expanded,
// and arrow-key expand/collapse)
new dhx.Grid("grid_container", {
columns, data,
type: "tree",
selection: "complex"
});

// WAI-ARIA semantics are always emitted — there is no flag to toggle them.

Related articles:

Host-page responsibilities

A few accessibility requirements live at the page level, not inside the component. Make sure the host document:

  • sets a document language, e.g. <html lang="en">;
  • provides a page <h1> and wraps the grid in an appropriate landmark (e.g. <main>);
  • gives the grid container an accessible name where multiple widgets share a page.

Reference