JavaScript Data GridLayout direction

Set the layout direction for right-to-left languages. Automatically inherit your HTML file's dir property, or set the layout direction manually.

Overview

To properly display Handsontable's UI and data in LTR languages (such as English, Chinese, or Russian) and RTL languages (such as Arabic, Persian, or Hebrew), configure your grid's layout direction.

By default, Handsontable's layout direction is set automatically, based on on the value of your HTML document's dir attribute.

You can:

RTL support

If your app uses an RTL language, we recommend setting Handsontable's layout direction to RTL.

For Arabic, use Handsontable's built-in Arabic translation. For any other RTL language, add your own translation.

RTL demo

To try out Handsontable's RTL support, check out the demo below:

import Handsontable from 'handsontable';
import { registerLanguageDictionary, arAR } from 'handsontable/i18n';
import 'handsontable/dist/handsontable.full.min.css';

registerLanguageDictionary(arAR);

// generate random RTL data (e.g., Arabic)
function generateArabicData() {
  const randomName = () =>
    ['عمر', 'علي', 'عبد الله', 'معتصم'][Math.floor(Math.random() * 3)];

  const randomCountry = () =>
    ['تركيا', 'مصر', 'لبنان', 'العراق'][Math.floor(Math.random() * 3)];

  const randomDate = () =>
    new Date(Math.floor(Math.random() * Date.now())).toLocaleDateString();

  const randomBool = () => Math.random() > 0.5;
  const randomNumber = (a = 0, b = 1000) => a + Math.floor(Math.random() * b);
  const randomPhrase = () =>
    `${randomCountry()} ${randomName()} ${randomNumber()}`;

  const arr = Array.from({ length: 10 }, () => [
    randomBool(),
    randomName(),
    randomCountry(),
    randomPhrase(),
    randomDate(),
    randomPhrase(),
    randomBool(),
    randomNumber(0, 200).toString(),
    randomNumber(0, 10),
    randomNumber(0, 5),
  ]);

  return arr;
}

const container = document.querySelector('#example1');

new Handsontable(container, {
  licenseKey: 'non-commercial-and-evaluation',
  data: generateArabicData(),
  colHeaders: true,
  rowHeaders: true,
  height: 'auto',
  // render Handsontable from the right to the left
  layoutDirection: 'rtl',
  // load an RTL language (e.g., Arabic)
  language: 'ar-AR',
  // enable a few options that exemplify the layout direction
  dropdownMenu: true,
  filters: true,
  contextMenu: true,
  autoWrapRow: true,
  autoWrapCol: true,
});

Elements affected by layout direction

Setting a different layout direction affects the behavior of the following areas of Handsontable:

Element LTR layout direction RTL layout direction
Starting edge The left-hand edge is treated as the starting edge of the grid. The right-hand edge is treated as the starting edge of the grid.
Ending edge The right-hand edge is treated as the ending edge of the grid. The left-hand edge is treated as the ending edge of the grid.
Order of columns on the screen Cell rendering flows from the left-hand side of the screen to right-hand side.

Cell (0, 0) is rendered in the grid's top-left corner.
Cell rendering flows from the right-hand side of the screen to left-hand side.

Cell (0, 0) is rendered in the grid's top-right corner.
Text direction in cells All cells inherit the LTR direction from the container element. All cells inherit the RTL direction from the container element.
Position of row headers Row headers are rendered on the left-hand edge of the grid. Row headers are rendered on the right-hand edge of the grid.
Position of frozen columns Columns are frozen at the left-hand edge of the grid. Columns are frozen at the right-hand edge of the grid.
Position of the fill handle The fill handle displays in the bottom-right corner of the selection border. The fill handle displays in the bottom-left corner of the selection border.
Position of the selection handles, on mobile devices On mobile devices, the selection handles display in the top-left and bottom-right corners of the selection border. On mobile devices, the selection handles display in the top-right and bottom-left corners of the selection border.
Custom borders In the customBorders option:

- The left-hand border is treated as the starting border.
- The right-hand border is treated as the ending border.
In the customBorders option:

- The right-hand border is treated as the starting border.
- The left-hand border is treated as the ending border.
Context menu and column menus Menus' layout direction is left-to-right.

Submenus expand to the right.
Menus' layout direction is right-to-left.

Submenus expand to the left.
Keyboard navigation Tab moves one cell to the right.

Shift+Tab moves one cell to the left.

Home moves to the leftmost non-frozen cell of the current row.

Ctrl/Cmd+Home moves to the top-left non-frozen cell of the grid.

Shift+Home extends the selection to the leftmost non-frozen cell of the current row.

End moves to the rightmost non-frozen cell of the current row.

Ctrl/Cmd+End moves to the bottom-right non-frozen cell of the grid.

Shift+End extends the selection to the rightmost non-frozen cell of the current row.

Delete deletes one character to the right of the cursor.

Backspace deletes one character to the left of the cursor.
Tab moves one cell to the left.

Shift+Tab moves one cell to the right.

Home moves to the rightmost non-frozen cell of the current row.

Ctrl/Cmd+Home moves to the top-right non-frozen cell of the grid.

Shift+Home extends the selection to the rightmost non-frozen cell of the current row.

End moves to the leftmost non-frozen cell of the current row.

Ctrl/Cmd+End moves to the bottom-left non-frozen cell of the grid.

Shift+End extends the selection to the leftmost non-frozen cell of the current row.

Delete deletes one character to the left of the cursor.

Backspace deletes one character to the right of the cursor.

The list above is not exhaustive. Setting a different layout direction might affect other areas of Handsontable as well.

Set the layout direction

You can set the layout direction only at Handsontable's initialization. Any change of the layoutDirection option after the initialization (e.g. using the updateSettings() method) is ignored.

Set the layout direction automatically

You can set Handsontable's layout direction automatically, based on on the value of your HTML document's dir attribute. This is the default setting.

At Handsontable's initialization, add layoutDirection as a top-level grid option, and set it to 'inherit'. As this is the default setting, you can also skip setting the layoutDirection option altogether.

In the example below, the RTL layout direction is inherited from a dir attribute up in the DOM tree:

import Handsontable from 'handsontable';
import 'handsontable/dist/handsontable.full.min.css';

const container = document.querySelector('#example2');

new Handsontable(container, {
  licenseKey: 'non-commercial-and-evaluation',
  data: [
    ['', 'Tesla', 'Volvo', 'Toyota', 'Ford'],
    ['2019', 10, 11, 12, 13],
    ['2020', 20, 11, 14, 13],
    ['2021', 30, 15, 12, 13],
  ],
  colHeaders: true,
  rowHeaders: true,
  height: 'auto',
  // inherit Handsontable's layout direction
  // from the value of your HTML document's `dir` attribute
  layoutDirection: 'inherit',
  autoWrapRow: true,
  autoWrapCol: true,
});

Set the layout direction to RTL

You can render Handsontable from the right to the left, regardless of your HTML document's dir attribute.

At Handsontable's initialization, add layoutDirection as a top-level grid option, and set it to 'rtl':

import Handsontable from 'handsontable';
import 'handsontable/dist/handsontable.full.min.css';

const container = document.querySelector('#example3');

new Handsontable(container, {
  licenseKey: 'non-commercial-and-evaluation',
  data: [
    ['', 'Tesla', 'Volvo', 'Toyota', 'Ford'],
    ['2019', 10, 11, 12, 13],
    ['2020', 20, 11, 14, 13],
    ['2021', 30, 15, 12, 13],
  ],
  colHeaders: true,
  rowHeaders: true,
  height: 'auto',
  // render Handsontable from the right to the left
  // regardless of your HTML document's `dir`
  layoutDirection: 'rtl',
  autoWrapRow: true,
  autoWrapCol: true,
});

Set the layout direction to LTR

You can render Handsontable from the left to the right, regardless of your HTML document's dir attribute.

At Handsontable's initialization, add layoutDirection as a top-level grid option, and set it to 'ltr':

import Handsontable from 'handsontable';
import 'handsontable/dist/handsontable.full.min.css';

const container = document.querySelector('#example4');

new Handsontable(container, {
  licenseKey: 'non-commercial-and-evaluation',
  data: [
    ['', 'Tesla', 'Volvo', 'Toyota', 'Ford'],
    ['2019', 10, 11, 12, 13],
    ['2020', 20, 11, 14, 13],
    ['2021', 30, 15, 12, 13],
  ],
  colHeaders: true,
  rowHeaders: true,
  height: 'auto',
  // render Handsontable from the left to the right
  // regardless of your HTML document's `dir`
  layoutDirection: 'ltr',
  autoWrapRow: true,
  autoWrapCol: true,
});

Set the horizontal text alignment

You can apply different horizontal text alignment settings, overwriting the horizontal text alignment resulting from your grid's layout direction.

In the example below, some columns are explicitly aligned to the left, center, or right:

import Handsontable from 'handsontable';
import 'handsontable/dist/handsontable.full.min.css';

const container = document.querySelector('#example5');

new Handsontable(container, {
  licenseKey: 'non-commercial-and-evaluation',
  data: [
    ['', 'Tesla', 'Volvo', 'Toyota', 'Ford'],
    ['2019', 10, 11, 12, 13],
    ['2020', 20, 11, 14, 13],
    ['2021', 30, 15, 12, 13],
  ],
  colHeaders: true,
  rowHeaders: true,
  height: 'auto',
  // render Handsontable from the right to the left
  // regardless of your HTML document's `dir`
  layoutDirection: 'rtl',
  columns: [
    {},
    // align this column's text to the left
    { className: 'htLeft' },
    // align this column's text to the center
    { className: 'htCenter' },
    // align this column's text to the right
    { className: 'htRight' },
    {},
  ],
  autoWrapRow: true,
  autoWrapCol: true,
});

You can apply the horizontal text alignment settings to:

There is a newer version of Handsontable available. Switch to the latest version ⟶