Accessibility
Jspreadsheet renders real DOM elements and exposes the ARIA grid model, so assistive technology reads the data grid as a grid of rows and cells, and every interaction is available from the keyboard. This page collects what the data grid does for accessibility and where the related settings are documented.
What's new with Version 13
- ARIA grid model:
gridcell, rows witharia-rowindex, column headers witharia-colindex, row headers,aria-rowcountandaria-colcounton the virtualized grid,aria-sorton sorted headers andaria-selectedon the cursor cell- Keyboard:
Ctrl + Arrowfollows the Excel block contract,Ctrl + DandCtrl + Rfill, and the keyboard navigation recovers when the browser window regains focus- Context menu: opens from the keyboard with
Shift + F10or the context menu key, and can be navigated with the arrows
Documentation
ARIA model
| Attribute or role | Where | Description |
|---|---|---|
role="grid" |
The table | The data grid is announced as a grid. |
aria-rowcount, aria-colcount |
The table | The full dimensions of the worksheet, even though only the visible cells are rendered. |
role="row", aria-rowindex |
Each rendered row | The one-based position of the row in the worksheet. |
role="columnheader", aria-colindex |
Each column header | The one-based position of the column. |
role="rowheader" |
The row number cell | The header of the row. |
role="gridcell" |
Each cell | A cell of the grid. |
aria-selected="true" |
The cursor cell | The cell that receives the keyboard input. |
aria-sort |
A sorted column header | ascending or descending; every level of a multi column sort carries its own value. |
Keyboard
The whole data grid is operable from the keyboard: cell navigation, block jumps, selection, editing, copy, cut and paste, fill, undo and redo, the context menu, the filters, the worksheets and the top menu. The complete list is in the shortcuts section, and custom shortcuts can be registered through jspreadsheet.shortcuts.set.
| Area | Keys |
|---|---|
| Navigation | Arrows, Tab, Enter, Page Up, Page Down, Ctrl + Arrow for the Excel block jumps |
| Selection | Shift + Arrow, Ctrl + Shift + Arrow, Ctrl + A |
| Editing | F2, typing to start, Enter and Tab to confirm, Esc to cancel, Delete to clear |
| Fill | Ctrl + D, Ctrl + R |
| Clipboard | Ctrl + C, Ctrl + X, Ctrl + V |
| History | Ctrl + Z, Ctrl + Y |
| Context menu | Shift + F10, the context menu key |
| Filters | Alt + Arrow Down opens the filter of the current column |
| Worksheets | Alt + Arrow Left, Alt + Arrow Right, Shift + F11 |
| Top menu | Alt focuses the menu bar when present |
Editors
The native editors support IME composition for languages that need it, and the dropdown, autocomplete and calendar widgets are navigable with the keyboard. Custom editors keep the same contract: an editor implemented as a web component receives the keyboard events of the cell. See the editors section.
Colour and contrast
The visual state of the grid is carried by CSS variables, so a theme can raise the contrast of the selection, the headers and the gridlines without touching the markup. The header of a fully selected column or row carries the jss_full class in addition to selected, and the row group outline emits jss_group_header and jss_group_level_1 to jss_group_level_8, so every state has a hook for a high contrast theme. See the themes section.
Settings that affect accessibility
| Setting | Description |
|---|---|
moveDownOnEnter: boolean |
Move the cursor down on Enter. Default: true. |
allowManualInsertRow, allowManualInsertColumn |
Create a new row or column with Enter or Tab on the last one. |
columnSortingOnDblClick: boolean |
Sort from the header with a double click, or Shift + double click to add a level. |
keyboardFormulas: boolean |
Enable the formula picker from the keyboard. Default: true. |
contextMenu |
The context menu items can be customized; the menu stays keyboard operable. |
Example
The example reads the ARIA attributes of the cursor cell after each move, which is what a screen reader announces.
<html>
<script src="https://jspreadsheet.com/v13/jspreadsheet.js"></script>
<script src="https://jsuites.net/v6/jsuites.js"></script>
<link rel="stylesheet" href="https://jspreadsheet.com/v13/jspreadsheet.css" type="text/css" />
<link rel="stylesheet" href="https://jsuites.net/v6/jsuites.css" type="text/css" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons" />
<div id="spreadsheet"></div>
<p id="status" aria-live="polite"></p>
<script>
// You can use the following license for quick testing on localhost, StackBlitz, or CodeSandbox.
// The license is valid for one day, after which the spreadsheet will become read-only.
// For a longer trial period, you can create a free account and generate a demo license with an extended expiration date.
jspreadsheet.setLicense('MTVhYThjNjY3ODk0MWYwM2I1ZDc3ZDhkY2RlNTU1Nzg3YTAyNGJhOWFkZmZlODBkYTk3NGFkMTEyMzhkZGJiNzRhMTQ1M2VjYmU3MjQ3Njc2NWIyODVkZjI0YWUwMWUxMGM1ZDFmMjRjYjZkZTNlZDZhZTAwNzgzNDYzZjgxNzcsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpnNE9ESTNORFU1TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2liRzlqWVd4b2IzTjBJbDBzSW5Cc1lXNGlPaUl6TkNJc0luTmpiM0JsSWpwYkluWTNJaXdpZGpnaUxDSjJPU0lzSW5ZeE1DSXNJbll4TVNJc0luWXhNaUlzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFXMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElpd2ljR2wyYjNRaVhTd2laR1Z0YnlJNmRISjFaWDA9');
// Create the spreadsheet
let worksheets = jspreadsheet(document.getElementById('spreadsheet'), {
worksheets: [{
data: [
['Product', 'Quantity', 'Price'],
['Apples', 12, 1.2],
['Pears', 7, 1.6],
['Grapes', 3, 4.1],
],
columns: [
{ title: 'Product', width: 140 },
{ title: 'Quantity', width: 100, type: 'number' },
{ title: 'Price', width: 100, type: 'number' },
],
}],
onselection: function(worksheet, x1, y1) {
let cell = worksheet.getCellFromCoords(x1, y1);
let row = cell.parentNode;
document.getElementById('status').textContent =
'Row ' + row.getAttribute('aria-rowindex') +
', column ' + (x1 + 1) +
', role ' + cell.getAttribute('role') +
', selected ' + cell.getAttribute('aria-selected');
},
});
</script>
</html>