Grid

Grids allow users to view and efficiently manipulate large amounts of data in a tabular format.

Accessibility Support

Out of the box, the Telerik and Kendo UI Grid provides extensive accessibility support and enables users with disabilities to acquire complete control over its features.

The Grid is compliant with the Web Content Accessibility Guidelines (WCAG) 2.2 standards and Section 508 requirements, follows the Web Accessibility Initiative - Accessible Rich Internet Applications (WAI-ARIA) best practices for implementing the keyboard navigation for its component role, provides options for managing its focus and is tested against the most popular screen readers.

WAI-ARIA

This section lists the selectors, attributes, and behavior patterns supported by the component and its composite elements, if any.

The Grid is a composite component that consists of 4 logically separated structural elements:

  • Toolbar (role=toolbar);
  • Group header (role=toolbar);
  • Data Grid (role=grid);
  • Pager (role=application);

Grid Toolbar

Grid Toolbar follows the specification of the ToolBar component.

SelectorAttributeUsage
.k-grid-toolbarrole=toolbarThe toolbar is a collection of command buttons and inputs.
aria-labelClarifies the purpose of the toolbar.
aria-controls=.k-grid-aria-root idPointing to the id of the element with role=grid.

Grid Grouping Header

Grid Grouping Header follows the specification of the ToolBar component.

SelectorAttributeUsage
.k-grouping-headerrole=toolbarThe Grouping header is a ToolBar (collection of buttons).
aria-labelClarifies the purpose of the header.
aria-controls=.k-grid-aria-root idPointing to the id of the element with role=grid.
.k-grouping-header .k-chip-list .k-chiprole=buttonIf the element used is not <button>, then the role must be specified.
.k-grouping-header .k-chip-listrole=none/The ChipList default listbox role is removed to keep the toolbar --> button roles hierarchy.
titlePresent on the element or its child if sorting is enabled for that field.

Data Grid (excluding Toolbars and Pager)

The element with role=grid must not include the ToolBar and the Pager elements as those do not belong to the role=grid element itself.

Grid element
SelectorAttributeUsage
.k-grid:not(.k-treelist) .k-grid-aria-rootrole=gridThe role specifies the element is a Data Grid.
.k-grid-aria-rootaria-colcountThe total number of columns in the Grid. Needed only for Virtual columns and Hidden columns scenarios, when not all columns are rendered in the DOM. If the total number of columns is unknown, the value of aria-colcount must be set to -1.
aria-rowcountThe total number of rows in the table (header rows + master rows + detail rows + data rows + footer rows + aggregates rows). Needed only when Paging (and more that 1 page is present in the component), Virtual rows, or Master/Detail rows (Hierarchical Grid, Detail Template Grid) are enabled. If data is also Grouped, the proper number of all rows could not be calculated. In that case the value must be set to -1.

In scenarios when master and detail rows are present in the Grid (Hierarchical Grid, Detail Template Grid), the aria-rowcount (the total number of rows) must be calculated: 2 * (total number of items) + header rows + footer rows. That is because for each item in the Grid there is a master row and a detail row duplicating this way the number of rows.

If the Grid is composed of a single table (there is no separate <table> element for its header), no role attributes should be set on its inner elements(<thead>, <body>, <tr>, <th>, and <td>). Their semantic meaning will be used instead.

Grid header
SelectorAttributeUsage
.k-grid-header-wrap>tablerole=presentation/noneNegates the default semantic role of the <table> element.
.k-grid-header-wrap>table>theadrole=rowgroupRequired as the owner <table> element has its semantic role removed.
.k-grid-header-wrap>table>thead>trrole=rowRequired as the owner <table> element has its semantic role removed.
aria-rowindexRow number including all headers, data (including master and detail) rows, and footers starting from 1. Needed only when Paging (and more that 1 page is present in the component), Virtual rows, or Master/Detail rows (Hierarchical Grid, Detail Template Grid) are enabled. If data is also Grouped, the proper indexing could not be calculated. Hence, the attribute must not be set.
.k-grid-header-wrap>table>thead>tr>th:not(.k-hierarchy-cell):not(.k-group-cell):not(.k-drag-cell)role=columnheaderRequired as the owner <table> element has its semantic role removed.
aria-sort=none/ascending/descendingPresent if sorting is enabled for that column.
title or aria-labelPresent on the element or its child if sorting is enabled for that field.
aria-colindexCol number, based on leaf columns, starting from 1. Needed only for Virtual columns and Hidden columns scenarios, when not all columns are rendered in the DOM. Otherwise, can be interpreted from the DOM structure. Can be calculated by summing previous columns colspans.
aria-haspopup=dialogThe attribute must be present if the column has a ColumnMenu.
aria-haspopup=dialogThe attribute must be present if the column has a FilterMenu and no ColumnMenu.
Grid filter row

Even if part of the <thead>, the Filter row must be composed of <td> elements.

SelectorAttributeUsage
.k-grid-header-wrap>table>thead>tr.k-filter-row>tdrole=gridcellRequired as the owner <table> element has its semantic role removed.
aria-labelHas a label indicating that the cell is part of a filter row.
Grid filter menu

Implements the FilterMenu specification.

Grid column menu

Implements the ColumnMenu specification.

Grid content
SelectorAttributeUsage
.k-grid-content>tablerole=none/presentationNegates the default semantic role of the <table> element.
.k-grid-content>table>tbodyrole=rowgroupRequired as the owner <table> element has its semantic role removed.
.k-grid-content>table>tbody>trrole=rowRequired as the owner <table> element has its semantic role removed.
aria-rowindexRow number including all headers, data (including master and detail) rows, and footers starting from 1. Needed only when Paging (and more that 1 page is present in the component), Virtual rows, or Master/Detail rows (Hierarchical Grid, Detail Template Grid) are enabled. If data is also Grouped, the proper indexing could not be calculated. Hence, the attribute must not be set. In scenarios when master and detail rows are present in the Grid (Hierarchical Grid, Detail Template Grid), both master and detail rows must always be indexed. For example, if the first master row has aria-rowindex=2, even if its detail row is not present in the DOM, the next master row must have aria-rowindex=4. When rendered, the detail row must receive the missing index between the two master rows. In this example it would be aria-rowindex=3.
.k-grid-content tr.k-selectedaria-selected=trueSet on the currently selected row(s). Only used wen selection mode is set to row.
.k-grid-content>table>tbody>tr>tdrole=gridcellRequired as the owner <table> element has its semantic role removed.
aria-colindexCol number, based on leaf columns, starting from 1. Needed only for Virtual columns and Hidden columns scenarios, when not all columns are rendered in the DOM. Otherwise, can be interpreted from the DOM structure. Can be calculated by summing previous columns colspans.
td.k-selectedaria-selected=trueSet on the currently selected cell(s). Only used when selection mode is set to cell.
.k-master-row .k-hierarchy-cell,.k-grouping-row>tdaria-expanded=true/falseOptionally for cells holding grouping criteria values and for Master row cells in Detail template scenario.
.k-drag-cellaria-labelMust be present in a Drag Row scenario on the cell containing the drag handle.
.k-grid-header-locked .k-grid-header-table .k-table-rowaria-ownsWhen there are locked columns, the rows from the locked header table should own the cells from the corresponding non-locked header table rows. Value should be a space-separated list of ids.
.k-grid-content-locked .k-grid-table .k-table-rowaria-ownsWhen there are locked columns, the rows from the locked content table should own the cells from the corresponding non-locked content table rows. Value should be a space-separated list of ids.
.k-grid-header-wrap .k-grid-header-table .k-table-rowrole=presentation/noneWhen there are locked columns, the rows from the non-locked header table should have their default semantic role removed, as their children are owned by the corresponding row from the locked table.
.k-grid-content .k-grid-table .k-table-rowrole=presentation/noneWhen there are locked columns, the rows from the non-locked content table should have their default semantic role removed, as their children are owned by the corresponding row from the locked table.
Grid footer

The Aggregates totals are placed within a <tfoot> element in the Content <table>.

SelectorAttributeUsage
tfootrole=rowgroupRequired as the owner <table> element has its semantic role removed.
tfoot>trrole=rowRequired as the owner <table> element has its semantic role removed.
aria-rowindexRow number including all headers, data (including master and detail) rows, and footers starting from 1. Footer rows are always the last ones in a Grid. Needed only when Paging (and more that 1 page is present in the component), Virtual rows, or Master/Detail rows (Hierarchical Grid, Detail Template Grid) are enabled. If data is also Grouped, the proper indexing could not be calculated. Hence, the attribute must not be set.
tfoot>tr>tdrole=gridcellRequired as the owner <table> element has its semantic role removed.
aria-colindexCol number, based on leaf columns, starting from 1. Needed only for Virtual columns and Hidden columns scenarios, when not all columns are rendered in the DOM. Otherwise, can be interpreted from the DOM structure. Can be calculated by summing previous columns colspans.

Pager

For the Grid Pager WAI-ARIA spec, please review the Pager component.

Grid selection aggregates

The selection aggregates are placed within a .k-grid-selection-aggregates element after the Grid .k-grid-aria-root element.

SelectorAttributeUsage
.k-grid-selection-aggregatesaria-live=politeEnsures that changes in the calculated selection aggregates are announced by assistive technologies.

Managing the Focus

The Grid component is a container that consists of 4 logically separated structural elements:

  • Toolbar (role="toolbar");
  • Group header (role="toolbar");
  • Data Grid (role="grid");
  • Pager (role="application");

Each of them is part of the page tab sequence and can be navigated to using the Tab key of the keyboard.

The Toolbar implements the keyboard navigation specification for a ToolBar component. Additionally, when the focus is on the search box, pressing the Esc key once clears the value, and pressing it a second time shifts the focus back to the ToolBar.

The Group heder implements the keyboard navigation specification for a ToolBar component. Delete buttons in the Field buttons should not be focusable. Deleting can be executed when Field name button is focused by pressing Delete or Backspace. After deleting a group (field button), the focus should be moved to the next field button (if present), or to the previous one. Upon deleting the last group (field button), the focus should be moved to the top-left data cell of the Grid.

The Pager implements the keyboard navigation specification for a Pager component.

The below description focuses only on the Data Grid part (the element with role="grid") of the composite component.

Data Grid Focus

The Data Grid is a single tab stop component. Upon focusing the Data Grid, the initial focus is set to either the previously focused cell (if any), or the first data (<td>) cell in the Data Grid. The change of the focused cell should be implemented using one of the following two techniques:

  • Roving TabIndex components Practice for managing the focus. Meaning that going through the cells will update the tabindex of the cell.
  • Active descendant - keeping the focus always on the Data Grid and using the aria-activedescendant on the Data Grid element which points to the id of the currently focused cell.

If a cell contains only one focusable element that does not itself require arrow keys for its inner navigation - focus goes to that element instead of its parent <td>.

If column header cells do not provide functions, such as sort, filter, grouping, or column menu, they may not be focusable.

If the Grid contains no items (empty Grid), the No data element in the Grid should be focused. That applies also for the scenario when the last item in the Grid has been deleted.

Keyboard Shortcuts

All Grid cells

ShortcutBehavior
Right ArrowMoves focus one cell to the right (if any)
Left ArrowMoves focus one cell to the left (if any)
Down ArrowMoves focus one cell down (if any)
Up ArrowMoves focus one cell up (if any)
HomeMoves focus to the first cell in the row that contains focus.
EndMoves focus to the last cell in the row that contains focus.
Ctrl/Cmd(Mac) + HomeMoves focus to the first (top-left) data cell in the grid.
Ctrl/Cmd(Mac) + EndMoves focus to the last cell in the last loaded row of the Grid.
Page DownLoads and displays the next page of data. If virtual scrolling is used, scrolls down with the number of visible items.
Page UpLoads and displays the previous page of data. If virtual scrolling is used, scrolls up with the number of visible items.
Ctrl/Cmd(MacOS) + Down Arrow(Optional) Moves focus 5 rows down (if possible) or to the last row (for faster navigation).
Ctrl/Cmd(MacOS) + Up Arrow(Optional) Moves focus 5 rows down (if possible) or to the first row (for faster navigation).

Grid data cells

All scenarios
ShortcutBehavior
EnterWhen the grid is in InCell EditMode - EditMode is activated. In hierarchy cell - expands /collapses the detail row. In grouping cell - expands /collapses the group. If the cell contains a focusable elements - focus moves to the first focusable element inside.
F2Enters edit mode when the Grid is in InCell EditMode.
EscIf editor is opened, cancels the edit and closes the editor. If focus is on an element inside a cell, returns the focus back to the cell.
In a row selection scenario
ShortcutBehavior
SpaceSelects the row holding the currently focused cell.
Ctrl + Space or Cmd + Enter(MacOS)Selects or deselects the current row, while persisting previously selected rows (only for selection mode "multiple").
Shift + SpacePerforms range selection, selects all the rows between the last selected one (with SPACE or mouse click) and the one holding the focused cell.
Shift + Up ArrowSelects the row above. When multiple selection is enabled, extends the selection to that row.
Shift + Down ArrowSelects the row below. When multiple selection is enabled, extends the selection to that row.
In a cell selection scenario
ShortcutBehavior
SpaceSelects the currently focused cell.
Ctrl + Space or Cmd + Enter(MacOS)Selects or deselects the currently focused cell, while persisting previously selected cells (only for selection mode "multiple").
Shift + SpacePerforms range selection, selects all the cells between the last selected one (with SPACE or mouse click) and the focused cell.
Shift + Up ArrowSelects the cell above. When multiple selection is enabled, extends the selection to that cell.
Shift + Down ArrowSelects the cell below. When multiple selection is enabled, extends the selection to that cell.
Shift + Left ArrowSelects the cell to the left. When multiple selection is enabled, extends the selection to that cell.
Shift + Right ArrowSelects the cell to the right. When multiple selection is enabled, extends the selection to that cell.

Grid header cells

ShortcutBehavior
EnterIf sorting is enabled, Sort is applied.
Alt + DownOpens the Column menu / Filter menu and moves focus to that menu.
EscCloses Filter or Column menu.
Ctrl + Space or Cmd + Enter(MacOS)Group/ungroup the focused column.
Ctrl/Cmd(Mac) + Left ArrowReorders the column with the previous one.
Ctrl/Cmd(Mac) + Right ArrowReorders the column with the next one.
Alt/Option(Mac) + Left ArrowResizes the column (decreases width in LTR, increases width RTL).
Alt/Option(Mac) + Right ArrowResizes the column (increases width in LTR, decreases width RTL).

Note that header cells can't contain arbitrary focusable elements if the Grid is sortable, as the Enter key is reserved for sorting. There should be an option to remap the Enter key if a user scenario requires focusable elements in the header.

Command column cells

ShortcutBehavior
EnterMoves focus inside the command column, and can trap the tab sequence. First button is focused. If a button is focused, triggers the button action.
EscIf a button is focused, returns focus to the command cell.
TabMoves focus to the next button in the column.
Shift + TabMoves focus to the previous button in the column.

When deleting Grid item (row) after focusing and pressing Enter on a Delete button, the focus should go to the cell in the same column on the next (if present), or the previous row (item).

Inline Edit Row

Triggering an edit in Inline mode focuses the first editor.

ShortcutBehavior
TabMoves to the next editor in the row.
EscapeCancels the row edit. The focus goes to the command cell from where the row edit was triggered.

Incell Edit Cell

When editing mode is incell, we have an excel-like navigation. When an editor is opened and focus is inside it, the following key combinations are in use.

ShortcutBehavior
TabMoves to the next editor in the row (closing current editor). It skips cells with Editable='false' and command columns. If focus is already on the last editable cell on the row, focus is moved to the first editable cell on the next row, and it's editor is opened. If we're already on the last row of the grid, focus remains on the cell, with the editor closed.
Shift + TabMoves to the previous editor in the row (closing current editor). It skips cells with Editable='false' and command columns. If focus is already on the first editable cell on the row, focus is moved to the last editable cell on the previous row, and it's editor is opened. If we're already on the first row of the grid, focus remains on the cell, with the editor closed.
EnterCommits changes for the edited item, and moves focus to the same cell on the row below, opening it for edit.
EscapeCancels the edit. The focus goes to the current cell.

Popup editor

Opening the popup editor focuses the first editor.

ShortcutBehavior
TabMoves to the next editor in the form.
EscapeCloses the editor. The focus goes to the command cell from where the popup was opened.
EnterTriggers a submit action for the editor, including validation.

Filter Row

ShortcutBehavior
Arrow Keystd elements receive focus as standard navigation in Grid.
EnterEnters in the td and focuses the first focusable element in it. All filter row components gain tabindex=0. Focus remains trapped inside the filter row.
TabGoes through the filter row components.
EscFocus goes to the td element wrapping the currently focused filter component.

Column Menu

The Grid Column menu implements the Column menu keyboard navigation spec.

ShortcutBehavior
Alt + Down ArrowOpens the ColumnMenu Popup when focus is on the Grid header cell or on the main column menu button (depending on whether the Grid is navigable or not). Focus is trapped and wrapped within the Popup.
TabNavigates to the next focusable element in the Popup. If current focus is on the last element, moves focus to the first focusable item in the Popup.
Shift + TabNavigates to the previous focusable element in the Popup. If current focus is on the first element, moves focus to the last focusable item in the Popup.
EnterFor column menu items, executes the currently focused item action. If item is expandable, expands or collapses the item.
EscapeCloses the ColumnMenu Popup and returns focus to the header cell or the main button.
Down Arrow & Up ArrowMoves the focus to the next/previous item when focus is in the ColumnChooser list of options.
SpaceToggles the checked state of the focused ColumnChooser option.
All internal components follow their own keyboard navigation when focused.

Filter Menu

The Filter menu implements the Filter menu keyboard navigation spec. After focusing the Filter menu, the focus is trapped within its contents. The user should not be allowed to tab-out of the menu.

ShortcutBehavior
Alt + Down ArrowOpens the FilterMenu Popup when focus is on the Grid header cell or on the main filter menu button (depending on whether the Grid is navigable or not). Focus is trapped and wrapped within the Popup.
TabNavigates to the next focusable element in the Popup. If current focus is on the last element, moves focus to the first focusable item in the Popup.
Shift + TabNavigates to the previous focusable element in the Popup. If current focus is on the first element, moves focus to the last focusable item in the Popup.
EnterFor button items, executes the currently focused button action.
EscapeCloses the FilterMenu Popup and returns focus to the header cell or the main button.
All internal components follow their own keyboard navigation when focused.

Group row

ShortcutBehavior
EnterExpands/Collapses the row

Detail Template master row

Detail template is accessed through the detail cell.

ShortcutBehavior
EnterToggles the detail template.
Arrow DownFocuses the detailed cell.
EnterIf on detail cell, focus the first focusable element inside the detail template (if any).
EscReturns the focus to the detail cell.

Checkbox column

The CheckBoxes in a Checkbox column always receive focus instead of their <td> parents. That is because they are the only element in the cell, which is also focusable.

ShortcutBehavior
SpaceToggle checkbox. Toggling the checkbox selects/deselects a row.
EscReturns focus to the cell.

Row reordering column

Row reordering scenarios

The cells, containing the drag handles in a dedicated Row reordering column, allow row reordering when focused.

ShortcutBehavior
Ctrl/Cmd(MacOS) + Shift + Down ArrowReorders the row with the next one when such is present.
Ctrl/Cmd(MacOS) + Shift + Up ArrowReorders the row with the previous one when such is present.

Testing

The Grid has been extensively tested automatically with axe-core and manually with the most popular screen readers.

Screen Readers

The Grid has been tested with the following screen readers and browsers combinations:

EnvironmentTool
FirefoxNVDA
ChromeJAWS
Microsoft EdgeJAWS

Resources

Feedback