Skip to content

Text Align

TextAlign adds text alignment to paragraphs, headings, and other block nodes. It supports left, center, right, and justify alignment with keyboard shortcuts and a toolbar dropdown that shows the current alignment icon.

Not included in StarterKit. Add it separately.

Click in a paragraph and use the alignment dropdown in the toolbar to switch between left, center, right, and justify. The dropdown icon changes to reflect the current alignment. Each paragraph below starts with a different alignment.

With the default theme. The toolbar shows an alignment dropdown with a dynamic icon, plus individual alignment buttons.

Click to try it out
import { Editor, Document, Paragraph, Text, TextAlign, defaultIcons } from '@domternal/core';
import '@domternal/theme';
const editorEl = document.getElementById('editor')!;
// Toolbar with alignment buttons
const toolbar = document.createElement('div');
toolbar.className = 'dm-toolbar';
toolbar.innerHTML = `<div class="dm-toolbar-group">
<button class="dm-toolbar-button" data-align="left">${defaultIcons.textAlignLeft}</button>
<button class="dm-toolbar-button" data-align="center">${defaultIcons.textAlignCenter}</button>
<button class="dm-toolbar-button" data-align="right">${defaultIcons.textAlignRight}</button>
<button class="dm-toolbar-button" data-align="justify">${defaultIcons.textAlignJustify}</button>
</div>`;
editorEl.before(toolbar);
const editor = new Editor({
element: editorEl,
extensions: [Document, Paragraph, Text, TextAlign],
content: '<p>Try aligning this text with the buttons above or keyboard shortcuts.</p>',
});
toolbar.addEventListener('click', (e) => {
const btn = (e.target as Element).closest<HTMLButtonElement>('[data-align]');
if (btn) editor.chain().focus().setTextAlign(btn.dataset.align!).run();
});

With the full ToolbarController, TextAlign renders as a dropdown with a dynamic icon that reflects the current alignment.

OptionTypeDefaultDescription
typesstring[]['heading', 'paragraph']Node types that support text alignment
alignmentsstring[]['left', 'center', 'right', 'justify']Allowed alignment values
defaultAlignmentstring'left'Default alignment (not rendered to HTML)
TextAlign.configure({
types: ['heading', 'paragraph'],
alignments: ['left', 'center', 'right'], // remove justify
defaultAlignment: 'left',
})

Sets the text alignment on all configured node types at the current selection. Returns false if the alignment value is not in the allowed alignments list.

editor.commands.setTextAlign('center');
// With chaining
editor.chain().focus().setTextAlign('right').run();

Resets the text alignment to the default value on all configured node types at the current selection.

editor.commands.unsetTextAlign();
KeyCommandDescription
Mod-Shift-LsetTextAlign('left')Align left
Mod-Shift-EsetTextAlign('center')Align center
Mod-Shift-RsetTextAlign('right')Align right
Mod-Shift-JsetTextAlign('justify')Justify

Mod is Cmd on macOS and Ctrl on Windows/Linux.

TextAlign does not register any input rules.

TextAlign registers a dropdown in the toolbar with the name textAlign in group alignment at priority 200.

DropdownIconGroupPriorityDynamic icon
textAligntextAlignLeftalignment200Yes

The dropdown contains four items:

ItemCommandIconShortcutActive when
alignLeftsetTextAlign('left')textAlignLeftMod-Shift-LtextAlign: 'left' on heading/paragraph
alignCentersetTextAlign('center')textAlignCenterMod-Shift-EtextAlign: 'center' on heading/paragraph
alignRightsetTextAlign('right')textAlignRightMod-Shift-RtextAlign: 'right' on heading/paragraph
alignJustifysetTextAlign('justify')textAlignJustifyMod-Shift-JtextAlign: 'justify' on heading/paragraph

The dropdown has dynamicIcon: true, which means the trigger button shows the icon of the currently active alignment instead of a fixed icon.

TextAlign uses addGlobalAttributes() to inject a textAlign attribute into the configured node types (default: heading and paragraph). This is a global attribute, not per-extension - it applies to existing node types without modifying their schema definitions.

The textAlign attribute is parsed from the style attribute of the HTML element:

parseHTML: (element) => element.style.textAlign || defaultAlignment

If no text-align style is present, the default alignment is used.

Non-default alignments render as an inline style attribute:

<!-- center alignment -->
<p style="text-align: center">Centered text</p>
<!-- default (left) alignment - no style attribute -->
<p>Left-aligned text</p>

Both commands operate on all configured types simultaneously:

  • setTextAlign validates the alignment value, then calls updateAttributes(type, { textAlign: alignment }) on each configured type. Returns true if at least one type was updated.
  • unsetTextAlign calls resetAttributes(type, 'textAlign') on each type to reset to the default value.
import { TextAlign } from '@domternal/core';
import type { TextAlignOptions } from '@domternal/core';
ExportTypeDescription
TextAlignExtensionThe text align extension
TextAlignOptionsTypeScript typeOptions for TextAlign.configure()

@domternal/core - TextAlign.ts