Skip to content
FrameworkJavaScript

Caret API: move, focus, and set cursor position

Control cursor position and selection within the editor.

Last updated Sep 8, 2026Edit this page on GitHub

Reaching the editor instance

The methods below run on the editor you created with new Blok(). They are available once editor.isReady resolves.

TypeScript
// You already hold the instance returned by the constructor.
const editor = new Blok({ holder: 'editor' });
await editor.isReady;

// Call any API method on it.
editor.caret.setToLastBlock('end');

Methods

caret.setToFirstBlock(position?, offset?)

boolean

Set caret to the first block with optional position and offset.

When to use

position accepts 'start'/'end'/'default'. It returns false if there is no block to land on.

TypeScript
// Set to start of first block
editor.caret.setToFirstBlock('start');

// Set to end of first block
editor.caret.setToFirstBlock('end');

// Offset applies only to the 'default' position —
// 'start' and 'end' place the caret at the boundary and ignore it
editor.caret.setToFirstBlock('default', 5);

caret.setToLastBlock(position?, offset?)

boolean

Set caret to the last block with optional position and offset.

When to use

Common after appending content. Drop the caret at the end of the new last block with 'end'.

TypeScript
// Focus last block at end
editor.caret.setToLastBlock('end');

// Focus last block at start
editor.caret.setToLastBlock('start');

caret.setToPreviousBlock(position?, offset?)

boolean

Move caret to the previous block.

When to use

Moves relative to the focused block. It returns false at the top edge, so use the return value to detect boundaries.

TypeScript
editor.caret.setToPreviousBlock('end');
// Caret now at end of previous block

caret.setToNextBlock(position?, offset?)

boolean

Move caret to the next block.

When to use

Mirror of setToPreviousBlock(). It returns false at the bottom edge.

TypeScript
editor.caret.setToNextBlock('start');
// Caret now at start of next block

caret.setToBlock(blockOrIdOrIndex, position?, offset?)

boolean

Set caret to a specific block by BlockAPI, ID, or index.

When to use

The most flexible setter: target by BlockAPI, id, or index. Prefer id/BlockAPI over index, because an index shifts as blocks move.

Parameters

ParameterTypeRequiredDefaultDescription
blockOrIdOrIndexBlockAPI | string | numberRequired—

Target block, given as a BlockAPI instance, block id, or numeric index.

position'start' | 'end' | 'default'—'default'

Where within the block to place the caret.

offsetnumber—0

Absolute character offset from the start of the block's current input. It applies only when position is 'default'. The values 'start' and 'end' place the caret at the boundary and ignore the offset.

Errors

  • blockOrIdOrIndex is a valid id or index that does not resolve to an existing block (unknown id or out-of-range index).

    For id and index inputs, check the boolean return value. Only a falsy result tells you the target was not found. Passing a null BlockAPI, such as an unchecked getById() result, is invalid input and throws, so null-check before calling.

TypeScript
// By index
editor.caret.setToBlock(0, 'end');
// → true if the caret moved, false if the target block doesn't exist

// By ID
editor.caret.setToBlock('block-123', 'start');

// By BlockAPI (getById can return null, so guard it)
const block = editor.blocks.getById('block-123');
if (block) {
  editor.caret.setToBlock(block);
}

caret.focus(atEnd?)

boolean

Set focus to the editor, optionally at the end of content.

When to use

A light way to focus the editor without choosing a block. Pass true for the end. Same as the top-level focus().

TypeScript
// Focus at start
editor.caret.focus();

// Focus at end
editor.caret.focus(true);

caret.updateLastCaretAfterPosition()

void

Update the "after" position of the most recent caret undo entry. Use it after async caret movements.

When to use

Call it after an async caret move. Then undo lands the caret where the user ended up, not where the operation started.

TypeScript
// After moving caret asynchronously
requestAnimationFrame(() => {
  editor.caret.setToBlock(0);
  editor.caret.updateLastCaretAfterPosition();
});