Nodes are the building blocks of content in Lexical. Every piece of content is represented by a node in the editor state tree.
Node Hierarchy
Lexical provides several base node classes:
- LexicalNode - Abstract base class for all nodes
- TextNode - Represents text content
- ElementNode - Container for child nodes
- DecoratorNode - Renders custom content
LexicalNode
The base class for all nodes. Cannot be instantiated directly.
Static Methods
getType
Returns the unique string type identifier for this node class.
clone
static clone(node: LexicalNode): LexicalNode
Creates a new node instance by cloning the provided node.
A new node instance with the same properties
importJSON
static importJSON(serializedNode: SerializedLexicalNode): LexicalNode
Deserializes a node from JSON.
serializedNode
SerializedLexicalNode
required
The serialized node data
Instance Methods
getType
Returns the type string for this node instance.
getKey
Returns this node’s unique key.
getLatest
Returns the latest version of this node from the active EditorState.
The latest version of this node
getWritable
Returns a mutable version of this node. Must be called inside editor.update().
A writable clone of this node
editor.update(() => {
const node = $getNodeByKey('some-key');
const writable = node.getWritable();
// Now you can mutate writable
});
getParent
getParent<T extends ElementNode>(): T | null
Returns this node’s parent node.
getParentOrThrow
getParentOrThrow<T extends ElementNode>(): T
Returns this node’s parent node or throws if none exists.
getTopLevelElement
getTopLevelElement(): ElementNode | DecoratorNode | null
Returns the highest ancestor that is not a root node.
getParents
getParents(): Array<ElementNode>
Returns all ancestor nodes up to the root.
getPreviousSibling
getPreviousSibling<T extends LexicalNode>(): T | null
Returns the previous sibling node.
getNextSibling
getNextSibling<T extends LexicalNode>(): T | null
Returns the next sibling node.
isAttached
Returns true if there is a path from this node to the root.
True if the node is attached to the editor state
isSelected
isSelected(selection?: BaseSelection): boolean
Returns true if this node is in the provided selection (or current selection).
The selection to check against (defaults to current selection)
True if the node is selected
remove
remove(preserveEmptyParent?: boolean): void
Removes this node from the editor state.
If false (default), removes parent if it becomes empty
replace
replace<N extends LexicalNode>(replaceWith: N, includeChildren?: boolean): N
Replaces this node with another node.
The node to replace this one with
Whether to transfer children to the new node
insertBefore
insertBefore(nodeToInsert: LexicalNode, restoreSelection?: boolean): LexicalNode
Inserts a node before this one as a sibling.
insertAfter
insertAfter(nodeToInsert: LexicalNode, restoreSelection?: boolean): LexicalNode
Inserts a node after this one as a sibling.
isBefore
isBefore(targetNode: LexicalNode): boolean
Returns true if this node comes before the target in the tree.
isParentOf
isParentOf(targetNode: LexicalNode): boolean
Returns true if this node is an ancestor of the target.
getTextContent
Returns the text content of this node.
getTextContentSize
getTextContentSize(): number
Returns the length of the text content.
createDOM
createDOMConfig: EditorConfig, editor: LexicalEditor): HTMLElement
Creates the DOM element for this node during reconciliation.
updateDOM
updateDOM(prevNode: this, dom: HTMLElement, config: EditorConfig): boolean
Updates the DOM element. Return true to recreate the DOM.
exportJSON
exportJSON(): SerializedLexicalNode
Serializes this node to JSON.
exportDOM
exportDOM(editor: LexicalEditor): DOMExportOutput
Exports this node as HTML.
TextNode
Represents text content with formatting.
Creating Text Nodes
import { $createTextNode } from 'lexical';
const textNode = $createTextNode('Hello world');
$createTextNode
function $createTextNode(text?: string): TextNode
$isTextNode
function $isTextNode(node: LexicalNode | null | undefined): node is TextNode
Type guard for TextNode.
TextNode Methods
getTextContent
Returns the text content.
setTextContent
setTextContent(text: string): this
Sets the text content.
Returns the format flags as a 32-bit integer.
hasFormat(type: TextFormatType): boolean
Returns true if the format type is applied.
Format type: ‘bold’, ‘italic’, ‘underline’, ‘strikethrough’, ‘code’, ‘subscript’, ‘superscript’, ‘highlight’, ‘lowercase’, ‘uppercase’, ‘capitalize’
setFormat(format: TextFormatType | number): this
Sets the text format.
toggleFormat(type: TextFormatType): this
Toggles a specific format on or off.
editor.update(() => {
const textNode = $createTextNode('Bold text');
textNode.toggleFormat('bold');
});
getStyle
Returns the inline CSS styles as a string.
setStyle
setStyle(style: string): this
Sets inline CSS styles.
CSS text (e.g., ‘color: red; font-size: 16px’)
getMode
Returns the text mode: ‘normal’, ‘token’, or ‘segmented’.
setMode
setMode(type: TextModeType): this
Sets the text mode.
isSimpleText
Returns true if this is a simple text node (type ‘text’, normal mode).
isToken
Returns true if in token mode (deleted as a unit).
isSegmented
Returns true if in segmented mode.
splitText
splitText(...splitOffsets: Array<number>): Array<TextNode>
Splits this text node at the specified offsets.
Character offsets to split at
editor.update(() => {
const textNode = $createTextNode('Hello World');
const [hello, world] = textNode.splitText(5); // Split at space
});
select
select(anchorOffset?: number, focusOffset?: number): RangeSelection
Creates a selection on this text node.
Anchor position (defaults to end)
Focus position (defaults to end)
ElementNode
A container node that can have children.
$isElementNode
function $isElementNode(node: LexicalNode | null | undefined): node is ElementNode
Type guard for ElementNode.
ElementNode Methods
getChildren
getChildren<T extends LexicalNode>(): Array<T>
Returns all child nodes.
getChildrenSize
getChildrenSize(): number
Returns the number of children.
isEmpty
Returns true if there are no children.
getFirstChild
getFirstChild<T extends LexicalNode>(): T | null
Returns the first child node.
getLastChild
getLastChild<T extends LexicalNode>(): T | null
Returns the last child node.
getChildAtIndex
getChildAtIndex<T extends LexicalNode>(index: number): T | null
Returns the child at the specified index.
append
append(...nodesToAppend: Array<LexicalNode>): this
Appends nodes as children.
editor.update(() => {
const paragraph = $createParagraphNode();
const text = $createTextNode('Hello');
paragraph.append(text);
});
clear
Removes all children.
splice
splice(
start: number,
deleteCount: number,
nodesToInsert: Array<LexicalNode>
): this
Inserts/removes children at an index.
Returns the element format flags.
getFormatType(): ElementFormatType
Returns the format type: ‘left’, ‘center’, ‘right’, ‘justify’, ‘start’, ‘end’, or ”.
setFormat(type: ElementFormatType): this
Sets the element alignment/format.
getIndent
Returns the indentation level.
setIndent
setIndent(indent: number): this
Sets the indentation level.
DecoratorNode
A node that renders custom content via a decorator.
$isDecoratorNode
function $isDecoratorNode<T>(node: LexicalNode | null | undefined): node is DecoratorNode<T>
Type guard for DecoratorNode.
DecoratorNode Methods
decorate
decorate(editor: LexicalEditor, config: EditorConfig): T
Returns the decorator value (e.g., a React component).
isInline
Returns true if the decorator is inline.
isIsolated
Returns true if the decorator is isolated from surrounding content.
isKeyboardSelectable
isKeyboardSelectable(): boolean
Returns true if the decorator can be selected via keyboard.
Built-in Node Types
ParagraphNode
import { $createParagraphNode, $isParagraphNode } from 'lexical';
const paragraph = $createParagraphNode();
LineBreakNode
import { $createLineBreakNode, $isLineBreakNode } from 'lexical';
const lineBreak = $createLineBreakNode();
TabNode
import { $createTabNode, $isTabNode } from 'lexical';
const tab = $createTabNode();
RootNode
import { $getRoot, $isRootNode } from 'lexical';
const root = $getRoot();
Creating Custom Nodes
Extend a base node class:
import { ElementNode } from 'lexical';
export class CustomNode extends ElementNode {
static getType(): string {
return 'custom';
}
static clone(node: CustomNode): CustomNode {
return new CustomNode(node.__key);
}
createDOM(config: EditorConfig): HTMLElement {
const element = document.createElement('div');
element.className = 'custom-node';
return element;
}
updateDOM(): boolean {
return false;
}
static importJSON(serializedNode: SerializedCustomNode): CustomNode {
return $createCustomNode();
}
exportJSON(): SerializedCustomNode {
return {
...super.exportJSON(),
type: 'custom',
version: 1,
};
}
}
export function $createCustomNode(): CustomNode {
return new CustomNode();
}
export function $isCustomNode(node: LexicalNode | null | undefined): node is CustomNode {
return node instanceof CustomNode;
}
Register with the editor:
const editor = createEditor({
nodes: [CustomNode]
});