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.
Selector | Attribute | Usage |
---|---|---|
.k-grid-toolbar | role=toolbar | The toolbar is a collection of command buttons and inputs. |
aria-label | Clarifies the purpose of the toolbar. | |
aria-controls=.k-grid-aria-root id | Pointing to the id of the element with role=grid . |
Grid Grouping Header
Grid Grouping Header follows the specification of the ToolBar component.
Selector | Attribute | Usage |
---|---|---|
.k-grouping-header | role=toolbar | The Grouping header is a ToolBar (collection of buttons). |
aria-label | Clarifies the purpose of the header. | |
aria-controls=.k-grid-aria-root id | Pointing to the id of the element with role=grid . | |
.k-grouping-header .k-chip-list .k-chip | role=button | If the element used is not <button> , then the role must be specified. |
.k-grouping-header .k-chip-list | role=none/ | The ChipList default listbox role is removed to keep the toolbar --> button roles hierarchy. |
title | Present 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
Selector | Attribute | Usage |
---|---|---|
.k-grid:not(.k-treelist) .k-grid-aria-root | role=grid | The role specifies the element is a Data Grid. |
.k-grid-aria-root | aria-colcount | The 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-rowcount | The 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
Selector | Attribute | Usage |
---|---|---|
.k-grid-header-wrap>table | role=presentation/none | Negates the default semantic role of the <table> element. |
.k-grid-header-wrap>table>thead | role=rowgroup | Required as the owner <table> element has its semantic role removed. |
.k-grid-header-wrap>table>thead>tr | role=row | Required as the owner <table> element has its semantic role removed. |
aria-rowindex | Row 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=columnheader | Required as the owner <table> element has its semantic role removed. |
aria-sort=none/ascending/descending | Present if sorting is enabled for that column. | |
title or aria-label | Present on the element or its child if sorting is enabled for that field. | |
aria-colindex | Col 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=dialog | The attribute must be present if the column has a ColumnMenu. | |
aria-haspopup=dialog | The 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.
Selector | Attribute | Usage |
---|---|---|
.k-grid-header-wrap>table>thead>tr.k-filter-row>td | role=gridcell | Required as the owner <table> element has its semantic role removed. |
aria-label | Has 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
Selector | Attribute | Usage |
---|---|---|
.k-grid-content>table | role=none/presentation | Negates the default semantic role of the <table> element. |
.k-grid-content>table>tbody | role=rowgroup | Required as the owner <table> element has its semantic role removed. |
.k-grid-content>table>tbody>tr | role=row | Required as the owner <table> element has its semantic role removed. |
aria-rowindex | Row 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-selected | aria-selected=true | Set on the currently selected row(s). Only used wen selection mode is set to row . |
.k-grid-content>table>tbody>tr>td | role=gridcell | Required as the owner <table> element has its semantic role removed. |
aria-colindex | Col 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-selected | aria-selected=true | Set on the currently selected cell(s). Only used when selection mode is set to cell. |
.k-master-row .k-hierarchy-cell,.k-grouping-row>td | aria-expanded=true/false | Optionally for cells holding grouping criteria values and for Master row cells in Detail template scenario. |
.k-drag-cell | aria-label | Must be present in a Drag Row scenario on the cell containing the drag handle. |
.k-grid-header-locked .k-grid-header-table .k-table-row | aria-owns | When 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 id s. |
.k-grid-content-locked .k-grid-table .k-table-row | aria-owns | When 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 id s. |
.k-grid-header-wrap .k-grid-header-table .k-table-row | role=presentation/none | When 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-row | role=presentation/none | When 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>
.
Selector | Attribute | Usage |
---|---|---|
tfoot | role=rowgroup | Required as the owner <table> element has its semantic role removed. |
tfoot>tr | role=row | Required as the owner <table> element has its semantic role removed. |
aria-rowindex | Row 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>td | role=gridcell | Required as the owner <table> element has its semantic role removed. |
aria-colindex | Col 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.
Selector | Attribute | Usage |
---|---|---|
.k-grid-selection-aggregates | aria-live=polite | Ensures 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
Shortcut | Behavior |
---|---|
Right Arrow | Moves focus one cell to the right (if any) |
Left Arrow | Moves focus one cell to the left (if any) |
Down Arrow | Moves focus one cell down (if any) |
Up Arrow | Moves focus one cell up (if any) |
Home | Moves focus to the first cell in the row that contains focus. |
End | Moves focus to the last cell in the row that contains focus. |
Ctrl/Cmd(Mac) + Home | Moves focus to the first (top-left) data cell in the grid. |
Ctrl/Cmd(Mac) + End | Moves focus to the last cell in the last loaded row of the Grid. |
Page Down | Loads and displays the next page of data. If virtual scrolling is used, scrolls down with the number of visible items. |
Page Up | Loads 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
Shortcut | Behavior |
---|---|
Enter | When 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. |
F2 | Enters edit mode when the Grid is in InCell EditMode. |
Esc | If 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
Shortcut | Behavior |
---|---|
Space | Selects 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 + Space | Performs 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 Arrow | Selects the row above. When multiple selection is enabled, extends the selection to that row. |
Shift + Down Arrow | Selects the row below. When multiple selection is enabled, extends the selection to that row. |
In a cell selection scenario
Shortcut | Behavior |
---|---|
Space | Selects 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 + Space | Performs range selection, selects all the cells between the last selected one (with SPACE or mouse click) and the focused cell. |
Shift + Up Arrow | Selects the cell above. When multiple selection is enabled, extends the selection to that cell. |
Shift + Down Arrow | Selects the cell below. When multiple selection is enabled, extends the selection to that cell. |
Shift + Left Arrow | Selects the cell to the left. When multiple selection is enabled, extends the selection to that cell. |
Shift + Right Arrow | Selects the cell to the right. When multiple selection is enabled, extends the selection to that cell. |
Grid header cells
Shortcut | Behavior |
---|---|
Enter | If sorting is enabled, Sort is applied. |
Alt + Down | Opens the Column menu / Filter menu and moves focus to that menu. |
Esc | Closes Filter or Column menu. |
Ctrl + Space or Cmd + Enter (MacOS) | Group/ungroup the focused column. |
Ctrl/Cmd(Mac) + Left Arrow | Reorders the column with the previous one. |
Ctrl/Cmd(Mac) + Right Arrow | Reorders the column with the next one. |
Alt/Option(Mac) + Left Arrow | Resizes the column (decreases width in LTR, increases width RTL). |
Alt/Option(Mac) + Right Arrow | Resizes 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
Shortcut | Behavior |
---|---|
Enter | Moves focus inside the command column, and can trap the tab sequence. First button is focused. If a button is focused, triggers the button action. |
Esc | If a button is focused, returns focus to the command cell. |
Tab | Moves focus to the next button in the column. |
Shift + Tab | Moves 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.
Shortcut | Behavior |
---|---|
Tab | Moves to the next editor in the row. |
Escape | Cancels 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.
Shortcut | Behavior |
---|---|
Tab | Moves 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 + Tab | Moves 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. |
Enter | Commits changes for the edited item, and moves focus to the same cell on the row below, opening it for edit. |
Escape | Cancels the edit. The focus goes to the current cell. |
Popup editor
Opening the popup editor focuses the first editor.
Shortcut | Behavior |
---|---|
Tab | Moves to the next editor in the form. |
Escape | Closes the editor. The focus goes to the command cell from where the popup was opened. |
Enter | Triggers a submit action for the editor, including validation. |
Filter Row
Shortcut | Behavior |
---|---|
Arrow Keys | td elements receive focus as standard navigation in Grid. |
Enter | Enters 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. |
Tab | Goes through the filter row components. |
Esc | Focus goes to the td element wrapping the currently focused filter component. |
Column Menu
The Grid Column menu implements the Column menu keyboard navigation spec.
Shortcut | Behavior |
---|---|
Alt + Down Arrow | Opens 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. |
Tab | Navigates 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 + Tab | Navigates 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. |
Enter | For column menu items, executes the currently focused item action. If item is expandable, expands or collapses the item. |
Escape | Closes the ColumnMenu Popup and returns focus to the header cell or the main button. |
Down Arrow & Up Arrow | Moves the focus to the next/previous item when focus is in the ColumnChooser list of options. |
Space | Toggles the checked state of the focused ColumnChooser option. |
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.
Shortcut | Behavior |
---|---|
Alt + Down Arrow | Opens 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. |
Tab | Navigates 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 + Tab | Navigates 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. |
Enter | For button items, executes the currently focused button action. |
Escape | Closes the FilterMenu Popup and returns focus to the header cell or the main button. |
Group row
Shortcut | Behavior |
---|---|
Enter | Expands/Collapses the row |
Detail Template master row
Detail template is accessed through the detail cell.
Shortcut | Behavior |
---|---|
Enter | Toggles the detail template. |
Arrow Down | Focuses the detailed cell. |
Enter | If on detail cell, focus the first focusable element inside the detail template (if any). |
Esc | Returns 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.
Shortcut | Behavior |
---|---|
Space | Toggle checkbox. Toggling the checkbox selects/deselects a row. |
Esc | Returns 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.
Shortcut | Behavior |
---|---|
Ctrl/Cmd(MacOS) + Shift + Down Arrow | Reorders the row with the next one when such is present. |
Ctrl/Cmd(MacOS) + Shift + Up Arrow | Reorders 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:
Environment | Tool |
---|---|
Firefox | NVDA |
Chrome | JAWS |
Microsoft Edge | JAWS |