Skip to content

Spatial Navigation

A JavaScript-based implementation for Spatial Navigation with gamepad support

spatialNavigation.init(['.square']);

Click on an element and move the focus with your keyboard arrow keys:

If you add a disabled property to a navigable element it will skip it when moving the focus

Initializes the spatial navigation.

type NavigableArea = {
area: string,
elements: (string | HTMLElement)[]
};
type NavigationInput = (string | HTMLElement)[] | NavigableArea[];
spatialNavigation.init(navigableElements: NavigationInput = [], overlap?: number);

The navigableElement can be:

spatialNavigation.init(['.square']);
const element = document.getElementById('myElement');
spatialNavigation.init([element]);
spatialNavigation.init([
{ area: 'square-1', elements: ['.square1'] },
{ area: 'square-2', elements: ['.square2'] },
]);

This will create different areas to separate the navigation. If you pass only selectors or HTMLElements directly, they will be saved to the default area.

The init method takes an optional second argument, overlap, which accepts a value between 0.01 and 1. The default value is 0.5 (50%). It specifies the percentage of acceptable overlap between the current element and the next potential element for navigation.

If you want the elements to overlap perfectly (without any offset) in order to navigate between them, set the overlap value to 1 (100%).

spatialNavigation.init(['.square'], 1);

If you set a value less than 0 or greater than 1, the default value (0.5) will be used

In the following example, when navigating to the right, square 3 will be skipped because it has a Y-offset of 51%, and the overlap parameter was not specified when calling the init method (defaulting to 0.5, or 50%). By specifying an overlap value of 0.55, square 3 will be considered a valid target, and moving right will focus on square 3.

spatialNavigation.init(['.square'], 0.55);

Type:

type area = string

The name of the area you want to be navigable

Type:

type elements = (string | HTMLElement)[]

An array of element selectors (strings) or HTMLElement references that will be navigable in this area. You can mix both types in the same array.

Removes the spatial navigation, listeners and actions.

spatialNavigation.deinit();

The same as .init() but only adds elements to areas and new areas. Use it after initialization.

Supports the same formats as init(): selector strings, HTMLElement references, or navigableArea objects with mixed types.

// Add selectors to default area
spatialNavigation.add(['.new-element']);
// Add HTMLElement references to default area
const newEl = document.getElementById('newItem');
spatialNavigation.add([newEl]);
// Add to named area with mixed types
const element = document.getElementById('sidebar-item');
spatialNavigation.add([
{ area: 'area-1', elements: ['.element', element] }
]);

default='default'

Remove all of the elements from an area. It uses the area name as an argument, if you don’t pass any arguments it will remove the elements from the default area.

spatialNavigation.remove(area: string = 'default');
spatialNavigation.remove('area-1');

default='default'

Focuses on the first element of an area.

spatialNavigation.focusFirst(area: string = 'default');

default='default'

Focuses on the last element of an area.

spatialNavigation.focusLast(area: string = 'default');

Switches to another area and focuses on the first element.

spatialNavigation.switchArea(area: string);

Unfocuses the currently focused element in a navigable area.

spatialNavigation.clearFocus();
type Direction = 'down' | 'up' | 'left' | 'right';
type CustomKeysInput = Partial<Record<Direction, KeyName | KeyName[]>>;
spatialNavigation.changeKeys(customDirections: CustomKeysInput, options = { clearCurrentActiveKeys: false });
spatialNavigation.changeKeys({ up: 'W', down: 's', left: 'a', right: 'd' }, { clearCurrentActiveKeys: true });

The method accepts an optional options object as a last argument. The available options are:

  • clearCurrentActiveKeys - Boolean. Defaults to false. If true, it clears all other keys except the provided ones. If false оr not specified the provided keys will just be added to the registered keys collection.

Resets the navigation keys to their default settings, restoring the key bindings to the standard navigation keys (arrow_up, arrow_down, arrow_left, arrow_right).

spatialNavigation.resetKeys();

Pauses the spatial navigation functionality. When paused, navigation keys will not move focus between elements. This is useful when you need to temporarily disable navigation, such as during modal dialogs or text input.

spatialNavigation.pause();

Resumes the spatial navigation functionality after it has been paused. Navigation keys will work normally again.

spatialNavigation.resume();

Example usage:

// Pause navigation when opening a modal
openModal();
spatialNavigation.pause();
// Resume navigation when closing the modal
closeModal();
spatialNavigation.resume();

Type: boolean

Returns true if the spatial navigation is enabled, otherwise false.

Type: HTMLElement | null | undefined

Returns the last focused element.

Type: boolean

Returns true if the spatial navigation is paused, otherwise false.

Type: Record<string, { elements: HTMLElement[], distance: number, overflow: { x: number, y: number } }>

Returns an object with all the registered areas.

The spatial-navigation registers actions that move the focus. You can use these from your code directly with

action.execute('move-focus-down'); // moves the focus down
action.execute('move-focus-up'); // moves the focus up
action.execute('move-focus-left'); // moves the focus left
action.execute('move-focus-right'); // moves the focus right