# How to Configure Tables with Dual Widths for DOCX Cross-Platform Compatibility

> Ensure tables render consistently across Word, Google Docs, and LibreOffice. Configure dual widths using DXA units for seamless cross-platform DOCX compatibility by summing column and cell widths.

- Repository: [Anthropic/skills](https://github.com/anthropics/skills)
- Tags: how-to-guide
- Published: 2026-02-16

---

**To ensure tables render consistently across Microsoft Word, Google Docs, and LibreOffice, you must define both table-level `columnWidths` and cell-level `width` properties using DXA units, ensuring the values sum exactly to the total table width.**

When generating Word documents programmatically using the `docx` JavaScript library within the [anthropics/skills](https://github.com/anthropics/skills) repository, tables require a specific dual-width configuration pattern. According to the specification in [`skills/docx/SKILL.md`](https://github.com/anthropics/skills/blob/main/skills/docx/SKILL.md), omitting either the table-level or cell-level width definitions causes rendering inconsistencies across different word processors.

## Why Dual Widths Are Required for Cross-Platform DOCX Tables

Word processing applications interpret table dimensions differently when width specifications are incomplete. Microsoft Word might auto-adjust column widths based on content, while Google Docs collapses tables entirely when percentages are used, and LibreOffice applies inconsistent spacing.

The critical excerpt from the skill definition states:

> **CRITICAL: Tables need dual widths** – set both `columnWidths` on the table **AND** `width` on each cell. Without both, tables render incorrectly on some platforms.
> — [SKILL.md line 175-186](https://github.com/anthropics/skills/blob/main/skills/docx/SKILL.md#L175-L186)

## The Three-Layer Width Configuration

To achieve cross-platform compatibility, you must configure widths at three distinct levels, all using **DXA units** (twentieths of a point, where 1 inch = 1440 DXA).

### 1. Table-Level Width

Define the total table width using `WidthType.DXA`. For a standard US Letter page with 1-inch margins, the content width is 9360 DXA (12240 DXA page width minus 2880 DXA for both margins).

```javascript
const tableWidth = 9360;

const table = new Table({
    width: { size: tableWidth, type: WidthType.DXA },
    // ... additional configuration
});

```

### 2. Column Widths Array

Provide a `columnWidths` array where the sum of all values exactly equals the table-level width. This array defines the relative sizing of each column.

```javascript
const columnWidths = [4680, 4680]; // Sum equals 9360

const table = new Table({
    width: { size: tableWidth, type: WidthType.DXA },
    columnWidths: columnWidths,
    // ... rows configuration
});

```

### 3. Cell-Level Width

Each `TableCell` must explicitly set its own `width` property to match the corresponding value from the `columnWidths` array. This redundancy ensures that all platforms interpret the cell dimensions identically.

```javascript
new TableCell({
    width: { size: columnWidths[0], type: WidthType.DXA },
    // ... other cell properties
})

```

## Complete Implementation Example

The following example demonstrates a complete, runnable implementation that creates a two-column table with consistent dual-width configuration:

```javascript
const {
    Document, Packer, Paragraph, Table, TableRow, TableCell,
    WidthType, BorderStyle, ShadingType,
} = require('docx');
const fs = require('fs');

// Define consistent border styling
const border = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };
const borders = { top: border, bottom: border, left: border, right: border };

// US Letter with 1-inch margins: 12240 - (2 * 1440) = 9360 DXA
const tableWidth = 9360;
const columnWidths = [4680, 4680]; // Must sum to tableWidth

const table = new Table({
    width: { size: tableWidth, type: WidthType.DXA },
    columnWidths: columnWidths,
    rows: [
        new TableRow({
            children: [
                new TableCell({
                    borders,
                    width: { size: columnWidths[0], type: WidthType.DXA },
                    shading: { fill: "D5E8F0", type: ShadingType.CLEAR },
                    margins: { top: 80, bottom: 80, left: 120, right: 120 },
                    children: [new Paragraph("Column A")]
                }),
                new TableCell({
                    borders,
                    width: { size: columnWidths[1], type: WidthType.DXA },
                    shading: { fill: "D5E8F0", type: ShadingType.CLEAR },
                    margins: { top: 80, bottom: 80, left: 120, right: 120 },
                    children: [new Paragraph("Column B")]
                })
            ]
        })
    ]
});

const doc = new Document({
    sections: [{ children: [table] }]
});

Packer.toBuffer(doc).then(buffer => {
    fs.writeFileSync('dual-width-table.docx', buffer);
    console.log('Document created successfully with dual-width configuration');
});

```

## Common Pitfalls and Platform-Specific Behavior

According to the width rules documented in [`skills/docx/SKILL.md`](https://github.com/anthropics/skills/blob/main/skills/docx/SKILL.md) (lines 13-18), several specific constraints prevent cross-platform compatibility issues:

- **Avoid Percentage Widths**: While the `docx` library supports `WidthType.PERCENTAGE`, Google Docs ignores percentage-based table widths, causing tables to collapse to minimum content width. Always use `WidthType.DXA`.

- **Exact Summation**: The sum of the `columnWidths` array must precisely equal the table-level width. Even a 1 DXA discrepancy can cause rounding errors in LibreOffice.

- **Cell Margins Are Internal**: When calculating widths, remember that cell margins (padding) are internal spacing and do not add to the cell width calculation. The `width` property defines the total cell width including margins.

## Summary

- **Dual-width configuration requires three synchronized values**: table-level `width`, `columnWidths` array, and individual cell `width` properties.
- **Use DXA units exclusively** (1 inch = 1440 DXA) rather than percentages to ensure compatibility with Google Docs and LibreOffice.
- **Column widths must sum exactly to the table width**, and each cell must reference the corresponding column width value.
- **Cell margins are internal padding** and do not affect the width calculation, but must be accounted for in content layout.
- **Reference implementation** is documented in [`skills/docx/SKILL.md`](https://github.com/anthropics/skills/blob/main/skills/docx/SKILL.md) within the [anthropics/skills](https://github.com/anthropics/skills) repository.

## Frequently Asked Questions

### What happens if I only set table-level width without cell-level widths?

If you omit the `width` property on individual `TableCell` instances, Microsoft Word may auto-adjust column widths based on content, while Google Docs and LibreOffice often render columns with inconsistent spacing or collapsed widths. According to the [`skills/docx/SKILL.md`](https://github.com/anthropics/skills/blob/main/skills/docx/SKILL.md) specification, both values are required for deterministic cross-platform rendering.

### Why does Google Docs break with percentage-based table widths?

Google Docs does not properly interpret `WidthType.PERCENTAGE` values when importing DOCX files, causing tables to collapse to their minimum content width regardless of the specified percentage. The [`skills/docx/SKILL.md`](https://github.com/anthropics/skills/blob/main/skills/docx/SKILL.md) documentation explicitly recommends using `WidthType.DXA` (twentieths of a point) for all width specifications to ensure consistent rendering across Microsoft Word, Google Docs, and LibreOffice.

### How do I calculate DXA units for custom page sizes?

One inch equals 1440 DXA units. For standard US Letter (8.5 × 11 inches) with 1-inch margins, calculate the content width as follows: page width (12240 DXA) minus left margin (1440 DXA) minus right margin (1440 DXA) equals 9360 DXA. For A4 or custom sizes, multiply the page width in inches by 1440, then subtract the margin DXA values accordingly.

### Can I use auto-fit or percentage widths for cross-platform compatibility?

No, `WidthType.AUTO` and `WidthType.PERCENTAGE` should be avoided for cross-platform compatibility. Auto-fit widths produce inconsistent column sizing between Microsoft Word and LibreOffice, while percentages cause rendering failures in Google Docs. The [`skills/docx/SKILL.md`](https://github.com/anthropics/skills/blob/main/skills/docx/SKILL.md) specification mandates using explicit DXA values at both the table and cell levels to guarantee consistent layout across all major word processing platforms.