---
title: "Tables"
description: "How tables, merged cells, header rows, column widths, and cell styling convert between DOCX and Tiptap."
canonical_url: "https://tiptap.dev/docs/conversion/content-types/structures-and-media/tables"
---

# Tables

How tables, merged cells, header rows, column widths, and cell styling convert between DOCX and Tiptap.

Tables convert between DOCX and Tiptap using the `table`, `tableRow`, `tableCell`, and `tableHeader` node types. Basic structure, colspan, column widths, and cell- and table-level styling (borders, backgrounds, vertical alignment, row height) round-trip. Header rows import correctly but are not preserved on export.

## What you need

The right table extension depends on whether you also use the Pages extension and whether you want DOCX-specific cell formatting (backgrounds, borders, vertical alignment, row height).

- **Recommended (DOCX-aware, no pagination):** [`ConvertKit`](https://tiptap.dev/docs/conversion/import/docx/convertkit.md). Its bundled `ConvertTableKit` provides `Table`, `TableRow`, `TableCell`, `TableHeader` with DOCX attributes (`width`, `indent`, `height`, `heightRule`, `background`, `verticalAlign`, per-side borders) preconfigured.
- **DOCX-aware with pagination:** [`@tiptap-pro/extension-pages-tablekit`](https://tiptap.dev/docs/pages/guides/pages-tablekit.md). Its table extensions internally extend ConvertKit's, so the same DOCX cell attributes (background, vertical alignment, per-side borders, height, height rule) flow through, this time rendered via CSS Grid so tables can split across page breaks. Use this stack instead of (not in addition to) ConvertKit's table overrides; see the [PagesTableKit guide](https://tiptap.dev/docs/pages/guides/pages-tablekit.md) "Scenario B" for the composition.
- **Minimum (no DOCX cell formatting):** [`@tiptap/extension-table`](https://tiptap.dev/docs/editor/extensions/nodes/table.md) (open source TableKit, not in StarterKit). Renders the basic table structure; cell backgrounds, borders, vertical alignment, and row height are stripped on schema validation.

All three setups register the same node names (`table`, `tableRow`, `tableCell`, `tableHeader`), so the import JSON shape is the same. The difference is which attributes survive the editor schema. Do not install more than one table stack at a time.

## Support overview

The editor column below assumes ConvertKit (or PagesTableKit, which inherits ConvertKit's table overrides). With the minimum setup, every row marked "Supported" for cell- and row-level attributes drops to "Attributes dropped by schema."

> **Attributes in context.content but not rendering?:**
>
> If you inspect `context.content` after import and see `background`, `borderTopWidth`, `height`, `heightRule`, etc. on cells and rows, but the editor renders a plain table without those styles, you are almost certainly using `@tiptap/extension-table` directly. Switch to [ConvertKit](https://tiptap.dev/docs/conversion/import/docx/convertkit.md) (or PagesTableKit if you also use the Pages extension); only their table extensions declare these attributes in the schema.

| Feature                 | Import                                                              | Editor (with ConvertKit)                                                 | Export        | Notes                                                                                                                                                                                    |
| ----------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Basic tables            | Supported                                                           | Supported                                                                | Supported     | Full width (fluid) by default; a table with an explicit width exports at that fixed width                                                                                                |
| Header rows             | Detected only when source DOCX has explicit `<w:tblHeader/>` markup | Renders as `tableHeader` nodes                                           | Not preserved | Word users who only visually format the first row (bold, shaded) without applying the "Repeat as header row" property get no `tableHeader` nodes on import                               |
| Colspan                 | Supported                                                           | Supported                                                                | Supported     | Full round-trip                                                                                                                                                                          |
| Rowspan                 | Supported                                                           | Supported                                                                | Supported     | A pre-scan across all rows builds a complete rowspan map before processing cells                                                                                                         |
| Column widths           | Supported                                                           | Supported                                                                | Supported     | Stored as `colwidth` array in pixels, converted to twips on export. Resized columns keep their proportions on a fluid table                                                              |
| Table borders           | Supported                                                           | Supported (outer edges plus the inside grid)                             | Supported     | A table's own outer and inside borders round-trip; a borderless table stays borderless                                                                                                   |
| Cell backgrounds        | Supported                                                           | Supported                                                                | Supported     | `background` round-trips as cell shading                                                                                                                                                 |
| Cell borders            | Supported                                                           | Supported (per-side `borderTop/Bottom/Left/Right` × `Width/Style/Color`) | Supported     | Per-cell borders round-trip; a cell border that differs from the table's is kept as an override                                                                                          |
| Cell vertical alignment | Supported                                                           | Supported                                                                | Supported     | `verticalAlign` (`top`, `middle`, `bottom`) round-trips                                                                                                                                  |
| Row height              | Supported                                                           | Supported (`exact` clips via `.cell-content` wrapper; `atLeast` grows)   | Supported     | `height` and `heightRule` round-trip                                                                                                                                                     |
| Cell margins            | Supported                                                           | Supported                                                                | Supported     | The table's own cell margins (`cellMarginTop`, `cellMarginRight`, `cellMarginBottom`, `cellMarginLeft` on the `table` node) round-trip. A table without them uses Word's default spacing |
| Global table styling    | N/A                                                                 | N/A                                                                      | Supported     | Via `tableOverrides` and `tableCellOverrides`                                                                                                                                            |

## Import

Import tables using the [editor extension](https://tiptap.dev/docs/conversion/import/docx/editor-extension.md) or the [REST API](https://tiptap.dev/docs/conversion/import/docx/rest-api.md). Both produce identical output.

The conversion service reads DOCX tables and produces `table`, `tableRow`, and `tableCell` or `tableHeader` nodes. Column widths are stored in the `colwidth` attribute as an array of pixel values. Cell backgrounds, borders, and vertical alignment are captured as cell attributes. Row height and height rule are captured as row attributes. The table's own borders and cell margins are captured as table attributes.

A row is emitted as `tableHeader` only when the source DOCX explicitly carries `<w:tblHeader/>` inside the row's `<w:trPr>`. This is the markup Word writes when the user enables "Repeat as header row at the top of each page" on a table. Documents whose first row is only visually formatted as a header (bold, shaded, larger font) without that property arrive as plain `tableCell` rows. To mark the first row as a header from the application side, walk the imported JSON in your `onImport` callback before `setEditorContent()` and convert each cell's `type` from `tableCell` to `tableHeader`.

Merged cells using colspan convert reliably. Rowspan is also fully supported. The converter performs a pre-scan across all rows to build a complete rowspan map before processing cells, correctly resolving Word's `vMerge` "continue" markers.

If your editor schema does not include table nodes, imported table content will be dropped. See the [invalid schema guide](https://tiptap.dev/docs/guides/invalid-schema.md) for handling strategies.

## Editor rendering

ConvertKit's `ConvertTableKit` is the recommended renderer for DOCX-imported tables: it extends the base table stack with the DOCX-specific cell and row attributes (backgrounds, borders, vertical alignment, height, height rule) and configures `cellMinWidth: 1` so DOCX spacer columns (1–15 px narrow columns used for layout) do not get inflated into visible gaps. See [the ConvertKit page](https://tiptap.dev/docs/conversion/import/docx/convertkit.md) for the full attribute set.

Install the setup that matches your needs:

```bash
# Recommended: ConvertKit (DOCX-aware, no pagination)
npm install @tiptap-pro/extension-convert-kit

# With pagination via the Pages extension
npm install @tiptap-pro/extension-pages-tablekit @tiptap-pro/extension-convert-kit

# Minimum: structure only, no DOCX cell formatting
npm install @tiptap/extension-table
```

```ts
// Recommended (ConvertKit's bundled ConvertTableKit, no separate import needed)
import { ConvertKit } from '@tiptap-pro/extension-convert-kit'

new Editor({ extensions: [ConvertKit] })
```

```ts
// With pagination: disable ConvertKit's table stack so PagesTableKit can take over
import { ConvertKit } from '@tiptap-pro/extension-convert-kit'
import { TableKit } from '@tiptap-pro/extension-pages-tablekit'

new Editor({
  extensions: [
    ConvertKit.configure({ table: false }),
    TableKit,
  ],
})
```

```ts
// Minimum (basic structure; cell- and row-level DOCX attributes dropped)
import StarterKit from '@tiptap/starter-kit'
import { TableKit } from '@tiptap/extension-table'

new Editor({
  extensions: [StarterKit, TableKit],
})
```

Tables render as HTML `<table>`, `<tr>`, `<td>` (or `<td><div class="cell-content">` with ConvertKit), and `<th>` elements. Column resizing is supported when `resizable: true` is set on the Table extension. The `colwidth` attribute from import controls initial column widths.

## Export

Export tables using the [editor extension](https://tiptap.dev/docs/conversion/export/docx/editor-extension.md) or the [REST API](https://tiptap.dev/docs/conversion/export/docx/rest-api.md). The extension supports [`tableOverrides` and `tableCellOverrides`](https://tiptap.dev/docs/conversion/export/docx/styles.md#element-overrides) for global table styling defaults. The REST API does not accept these overrides.

A table with an explicit width exports at that fixed width; a table with no width set exports full width (fluid) so it reflows to the page. Column widths come from each cell's `colwidth`, or are split evenly when none is set. On a fluid table, resized columns keep their proportions.

Header rows are not preserved: every row is exported the same way, so the header-row semantics of the first row are lost in the output. Merged cells (colspan and rowspan) export correctly.

> **Cell and table styling round-trips on export:**
>
> Table borders (outer edges and the inside grid), cell margins, cell backgrounds, per-cell borders, vertical alignment, and row height are written to the DOCX on export. A borderless table stays borderless. A table without its own cell margins uses Word's default spacing. You can still set document-wide defaults with [`tableOverrides` and `tableCellOverrides`](https://tiptap.dev/docs/conversion/export/docx/styles.md#element-overrides) on the editor extension; these are not available via the REST API.

### Override system

The export extension accepts two options for global table styling:

```ts
ExportDocx.configure({
  tableOverrides: {
    borders: {
      top: { style: 'single', size: 4, color: '000000' },
      bottom: { style: 'single', size: 4, color: '000000' },
      left: { style: 'single', size: 4, color: '000000' },
      right: { style: 'single', size: 4, color: '000000' },
      insideHorizontal: { style: 'single', size: 4, color: '000000' },
      insideVertical: { style: 'single', size: 4, color: '000000' },
    },
  },
  tableCellOverrides: {
    shading: { fill: 'F5F5F5' },
  },
})
```

These overrides apply document-wide as defaults. Each cell's own styling (background, per-side borders, vertical alignment) and the table's own borders and cell margins are exported from the node attributes on top of those defaults.
