Skip to main content
The Table extension allows you to create tables with advanced features like cell merging, column resizing, and header rows. It requires the TableRow, TableCell, and TableHeader extensions to function.

Installation

npm install @tiptap/extension-table @tiptap/extension-table-row @tiptap/extension-table-cell @tiptap/extension-table-header

Usage

import { Editor } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import Table from '@tiptap/extension-table'
import TableRow from '@tiptap/extension-table-row'
import TableCell from '@tiptap/extension-table-cell'
import TableHeader from '@tiptap/extension-table-header'

const editor = new Editor({
  extensions: [
    Document,
    Paragraph,
    Text,
    Table,
    TableRow,
    TableCell,
    TableHeader,
  ],
})

Configuration

HTMLAttributes

Custom HTML attributes to add to the table element.
HTMLAttributes
Record<string, any>
default:"{}"
Custom HTML attributes that should be added to the rendered HTML tag.
Table.configure({
  HTMLAttributes: {
    class: 'my-table',
  },
})

resizable

Enables column resizing for tables.
resizable
boolean
default:"false"
When enabled, users can resize table columns by dragging column borders.
Table.configure({
  resizable: true,
})

renderWrapper

Controls whether the table should be wrapped in a div.
renderWrapper
boolean
default:"false"
Wraps the table in a div with class “tableWrapper” when rendered.
Table.configure({
  renderWrapper: true,
})

handleWidth

The width of the resize handle.
handleWidth
number
default:"5"
Width in pixels of the column resize handle.
Table.configure({
  resizable: true,
  handleWidth: 10,
})

cellMinWidth

The minimum width of a cell.
cellMinWidth
number
default:"25"
Minimum width in pixels that a table cell can be resized to.
Table.configure({
  resizable: true,
  cellMinWidth: 50,
})

lastColumnResizable

Enables resizing of the last column.
lastColumnResizable
boolean
default:"true"
When false, the last column cannot be resized.
Table.configure({
  resizable: true,
  lastColumnResizable: false,
})

allowTableNodeSelection

Allow table node selection.
allowTableNodeSelection
boolean
default:"false"
When enabled, users can select the entire table as a node.
Table.configure({
  allowTableNodeSelection: true,
})

Commands

insertTable

Inserts a new table with the specified dimensions.
editor.commands.insertTable({ rows: 3, cols: 3, withHeaderRow: true })

// Without header row
editor.commands.insertTable({ rows: 4, cols: 4, withHeaderRow: false })

addColumnBefore

Adds a column before the current column.
editor.commands.addColumnBefore()

addColumnAfter

Adds a column after the current column.
editor.commands.addColumnAfter()

deleteColumn

Deletes the current column.
editor.commands.deleteColumn()

addRowBefore

Adds a row before the current row.
editor.commands.addRowBefore()

addRowAfter

Adds a row after the current row.
editor.commands.addRowAfter()

deleteRow

Deletes the current row.
editor.commands.deleteRow()

deleteTable

Deletes the entire table.
editor.commands.deleteTable()

mergeCells

Merges the currently selected cells.
editor.commands.mergeCells()

splitCell

Splits the currently selected cell.
editor.commands.splitCell()

toggleHeaderColumn

Toggles the header status of the current column.
editor.commands.toggleHeaderColumn()

toggleHeaderRow

Toggles the header status of the current row.
editor.commands.toggleHeaderRow()

toggleHeaderCell

Toggles the header status of the current cell.
editor.commands.toggleHeaderCell()

mergeOrSplit

Merges selected cells or splits the current cell.
editor.commands.mergeOrSplit()

setCellAttribute

Sets an attribute on the current cell.
editor.commands.setCellAttribute('backgroundColor', '#ff0000')
editor.commands.setCellAttribute('align', 'right')

goToNextCell

Moves the selection to the next cell.
editor.commands.goToNextCell()

goToPreviousCell

Moves the selection to the previous cell.
editor.commands.goToPreviousCell()

fixTables

Attempts to fix the table structure if necessary.
editor.commands.fixTables()

setCellSelection

Sets a cell selection inside the current table.
editor.commands.setCellSelection({ anchorCell: 1, headCell: 5 })

Keyboard Shortcuts

  • Tab: Move to the next cell (creates a new row if at the end)
  • Shift-Tab: Move to the previous cell
  • Backspace: Delete table when all cells are selected
  • Mod-Backspace: Delete table when all cells are selected
  • Delete: Delete table when all cells are selected
  • Mod-Delete: Delete table when all cells are selected

Examples

Basic Table

// Insert a 3x3 table with header row
editor.commands.insertTable({ rows: 3, cols: 3, withHeaderRow: true })

Resizable Table

const editor = new Editor({
  extensions: [
    // other extensions...
    Table.configure({
      resizable: true,
      cellMinWidth: 50,
    }),
    TableRow,
    TableCell,
    TableHeader,
  ],
})

Manipulating Tables

// Add a row after the current row
editor.commands.addRowAfter()

// Add a column before the current column
editor.commands.addColumnBefore()

// Merge selected cells
editor.commands.mergeCells()

// Delete the current row
editor.commands.deleteRow()
The Table extension requires these companion extensions:
  • TableRow - Defines table rows (tr elements)
  • TableCell - Defines regular table cells (td elements)
  • TableHeader - Defines header cells (th elements)
All four extensions must be registered together for tables to work properly.

Source Code

View the source code on GitHub: packages/extension-table/src/table/table.ts