Export custom styles to .docx

When exporting to DOCX, you can define custom styles that will be applied to the exported document. This is useful when you want to have a consistent look and feel across your documents.

// Import the ExportDocx extension
import { ExportDocx } from '@tiptap-pro/extension-export-docx'

const editor = new Editor({
  extensions: [
    // Other extensions ...
    ExportDocx.configure({
      onCompleteExport: (result: string | Buffer<ArrayBufferLike> | Blob | Stream) => {}, // required
      styleOverrides: { // Style overrides
        paragraphStyles: [
          // Heading 1 style override
          {
            id: 'Heading1',
            name: 'Heading 1',
            basedOn: 'Normal',
            next: 'Normal',
            quickFormat: true,
            run: {
              font: 'Aptos',
              size: pointsToHalfPoints(16),
              bold: true,
              color: 'FF0000',
            },
            paragraph: {
              spacing: {
                before: pointsToTwips(12),
                after: pointsToTwips(6),
                line: lineHeightToDocx(1.15),
              },
            },
          },
        ]
      }
    }),
    // Other extensions ...
  ],
  // Other editor settings ...
})

In the example above ☝️ we are exporting a document with a custom Heading 1 style. The style is based on the Normal style, has a red color, and uses the Aptos font. The spacing before the paragraph is set to 12pt, and 6pt after it. The line height is set to 1.15.

You can also create custom styling for other elements like Heading 2, Heading 3, List Bullet, List Number, etc. The paragraphStyles array accepts an array of objects with the following properties:

Paragraph style object

A paragraphStyle object accepts the following properties:

PropertyTypeDescription
idstringUnique identifier for the style.
namestringDisplay name of the style.
basedOnstringThe base style (e.g., Normal) that this style builds upon.
nextstringThe style to apply to the following paragraph.
quickFormatbooleanIf true, the style appears in the quick format menu.
runobjectDefines text formatting (font, size, color, bold, etc.).
paragraphobjectDefines paragraph formatting (spacing, alignment, borders, etc.).

Run style properties

The run object from a paragraphStyle accepts the following properties:

PropertyTypeDescription
fontstringFont family for the text.
sizenumberFont size in half-points (e.g., 16 points = 32).
boldbooleanSet to true to make the text bold.
italicsbooleanSet to true for italic text.
colorstringText color in hex format (e.g., FF0000 for red. No # necessary).
kernnumberAdjusts the spacing between characters in points.
effectSpecial text effects that can be applied.
emphasisMarkstringEmphasis marks that appear above or below text. (like dot)
smallCapsbooleanSet to true to display text in small capitals.
allCapsbooleanSet to true to display text in all uppercase.
strikebooleanSet to true to apply a single strikethrough.
doubleStrikebooleanSet to true to apply a double strikethrough.
subScriptbooleanSet to true for subscript text.
superScriptbooleanSet to true for superscript text.
highlightHighlight color (predefined values).
characterSpacingnumberAdjusts spacing between characters in TWIPs (…we know, TWIPs right?
shadingobjectApplies background shading to the text.
shadingtypeShadingTypeThe shading type (clear, solid, horizontalStripe, etc.).
shadingfillstringThe shading fill color in hex format (e.g., FF0000 for red).
shadingcolorstringThe shading color in hex format (e.g., FF0000 for red).
scalenumberAdjusts the width of the text (as a percentage).
underlineobjectUnderline style, specify properties like color and type or and empty object for a simple underline.
underlinecolorstringUnderline color in hex format (e.g., FF0000 for red. No # necessary).
underlinetypeUnderlineTypeThe underline type (single, double or thick)

For more advanced styling options and detailed usage you can refer to the IRunStylePropertiesOptions type exposed from our package, or refer to the docx documentation.

Paragraph style properties

The paragraph object from a paragraphStyle accepts the following properties:

PropertyTypeDescription
spacingobjectControls spacing: properties like before, after, and line.
alignmentstringSets paragraph alignment (left, center, right, or justify).
borderobjectDefines borders around the paragraph (top, bottom, left, right).
shadingobjectApplies background shading to the paragraph.
indentobjectSpecifies indentation (first line, hanging, left, right).
contextualSpacingbooleanIf true, reduces spacing between paragraphs of the same style.
keepNextbooleanKeeps this paragraph on the same page as the next.
keepLinesbooleanKeeps all lines of the paragraph together on the same page.
outlineLevelnumberSets the outline level for document organization (typically 1–9).
thematicBreaknumberAdds a horizontal line break when set to true.
rightTabStopnumberSets the position of the right tab stop in twips.
leftTabStopnumberSets the position of the left tab stop in twips.
numberingobjectControls numbering settings (e.g., reference, level, custom formatting).
numberingreferencestringThe numbering style reference ID.
numberinglevelnumberThe level in the numbering hierarchy (0-based).
spacingobjectControls the spacing of the paragraph.
spacingbeforenumberSpace before the paragraph.
spacingafternumberSpace after the paragraph.
spacinglinenumberLine spacing within the paragraph.
spacinglineRuleLineRuleTypeDefines how the line spacing is calculated.

For more advanced styling options and detailed usage you can refer to the IParagraphStylePropertiesOptions type exposed from our package, or refer to the docx documentation.

Tiptap's export default styles

Tiptap offers a sensible default styling for the exported document, but you can override these styles by providing your own custom styles. This allows you to create a consistent look and feel across your documents.

{
  paragraphStyles: [
    // Normal style (default for most paragraphs)
    {
      id: 'Normal',
      name: 'Normal',
      run: {
        font: 'Aptos',
        size: pointsToHalfPoints(11),
      },
      paragraph: {
        spacing: {
          before: 0,
          after: pointsToTwips(10),
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // List Paragraph style (used for bullets and numbering)
    {
      id: 'ListParagraph',
      name: 'List Paragraph',
      basedOn: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos',
        size: pointsToHalfPoints(11),
      },
      paragraph: {
        spacing: {
          before: 0,
          after: pointsToTwips(2),
          line: lineHeightToDocx(1),
        },
      },
    },
    // Heading 1 style
    {
      id: 'Heading1',
      name: 'Heading 1',
      basedOn: 'Normal',
      next: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos Light',
        size: pointsToHalfPoints(16),
        bold: true,
        color: '2E74B5',
      },
      paragraph: {
        spacing: {
          before: pointsToTwips(12),
          after: pointsToTwips(6),
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // Heading 2 style
    {
      id: 'Heading2',
      name: 'Heading 2',
      basedOn: 'Normal',
      next: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos Light',
        size: pointsToHalfPoints(14),
        bold: true,
        color: '2E74B5',
      },
      paragraph: {
        spacing: {
          before: pointsToTwips(12),
          after: pointsToTwips(6),
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // Heading 3 style
    {
      id: 'Heading3',
      name: 'Heading 3',
      basedOn: 'Normal',
      next: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos',
        size: pointsToHalfPoints(13),
        bold: true,
        color: '2E74B5',
      },
      paragraph: {
        spacing: {
          before: pointsToTwips(12),
          after: pointsToTwips(6),
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // Heading 4 style
    {
      id: 'Heading4',
      name: 'Heading 4',
      basedOn: 'Normal',
      next: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos',
        size: pointsToHalfPoints(12),
        bold: true,
        color: '2E74B5',
      },
      paragraph: {
        spacing: {
          before: pointsToTwips(12),
          after: pointsToTwips(6),
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // Heading 5 style
    {
      id: 'Heading5',
      name: 'Heading 5',
      basedOn: 'Normal',
      next: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos',
        size: pointsToHalfPoints(11),
        bold: true,
        color: '2E74B5',
      },
      paragraph: {
        spacing: {
          before: pointsToTwips(12),
          after: pointsToTwips(6),
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // Title style
    {
      id: 'Title',
      name: 'Title',
      basedOn: 'Normal',
      next: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos Light',
        size: pointsToHalfPoints(22),
        bold: true,
        color: '000000',
      },
      paragraph: {
        alignment: AlignmentType.CENTER,
        spacing: {
          before: 0,
          after: 0,
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // Subtitle style
    {
      id: 'Subtitle',
      name: 'Subtitle',
      basedOn: 'Normal',
      next: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos Light',
        size: pointsToHalfPoints(16),
        italics: true,
        color: '666666',
      },
      paragraph: {
        alignment: AlignmentType.CENTER,
        spacing: {
          before: 0,
          after: 0,
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // Quote style (typically for indented, italic text)
    {
      id: 'Quote',
      name: 'Quote',
      basedOn: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos',
        italics: true,
      },
      paragraph: {
        alignment: AlignmentType.CENTER,
        spacing: {
          before: pointsToTwips(10),
          after: pointsToTwips(10),
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // Intense Quote style (more pronounced indentation)
    {
      id: 'IntenseQuote',
      name: 'Intense Quote',
      basedOn: 'Normal',
      quickFormat: true,
      run: {
        font: 'Aptos',
        italics: true,
        color: '444444',
      },
      paragraph: {
        alignment: AlignmentType.CENTER,
        spacing: {
          before: pointsToTwips(10),
          after: pointsToTwips(10),
          line: lineHeightToDocx(1.15),
        },
      },
    },
    // No Spacing style (no extra space before or after paragraphs)
    {
      id: 'NoSpacing',
      name: 'No Spacing',
      basedOn: 'Normal',
      quickFormat: true,
      paragraph: {
        spacing: {
          before: 0,
          after: 0,
          line: lineHeightToDocx(1),
        },
      },
    },
    // Hyperlink style
    {
      id: 'Hyperlink',
      name: 'Hyperlink',
      basedOn: 'Normal',
      run: {
        color: '0563C1',
        underline: {
          type: 'single',
        },
      },
    },
  ],
}