Learn dom-docx

Copy-paste examples for the most common integration paths. Pass a body HTML fragment only — no <!DOCTYPE> or wrapper required. Defaults: US Letter, 1″ margins, Arial 10.5pt body text.

Getting started

Install the package. The default styleSource: "inline" path is pure JavaScript — no browser or Playwright required on Node or in the browser bundle.

Terminal
// browser or Node
npm install dom-docx

// optional — render computed styles on Node
npm install playwright && npx playwright install chromium

Requires Node.js ≥ 20 for server-side use. For styleSource: "computed" on Node, install Playwright (an optional peer dependency) and its Chromium yourself, once, as shown above. The browser bundle never uses Playwright — computed styles read from the live DOM instead.

Quick start — browser, inline styles

Use dom-docx/browser when HTML is already in your app (React, Vue, etc.). Inline styles work on a string fragment with no rendered page. Returns a Blob you can download.

Browser · inline styles
import { convertHtmlToDocx } from "dom-docx/browser";

const html = `
<h1 style="color:#1a1a2e">Quarterly Report</h1>
<p>Revenue grew <strong>12%</strong> year over year.</p>
<ul>
  <li>North America</li>
  <li>EMEA</li>
</ul>
`;

const blob = await convertHtmlToDocx(html, { styleSource: "inline" });

// trigger download (example)
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "report.docx";
a.click();
URL.revokeObjectURL(url);

Try it live on the converter page — the site installs dom-docx from npm and bundles it with Vite.

Computed styles — browser

When HTML uses <style> blocks or CSS classes instead of inline style="", set styleSource: "computed". The fragment must already be rendered in document.body — the converter reads native getComputedStyle from the live page. No Playwright, no headless Chromium.

Browser · computed styles
import { convertHtmlToDocx } from "dom-docx/browser";

const html = `
<style>
  .hero { background: #eaeaea; padding: 10px 16px; }
  .hero h1 { color: #1a1a2e; margin: 0; }
</style>
<div class="hero">
  <h1>Title</h1>
</div>
`;

// Render the same fragment in the live DOM first
document.body.innerHTML = html;

const blob = await convertHtmlToDocx(html, { styleSource: "computed" });

With a React or Vue app, convert from the component’s rendered DOM — do not pass a string that was never mounted. The converter does not inject HTML into the page for you.

Image resolver

Only data: URLs embed automatically. For http(s):, file:, or relative paths, pass an imageResolver. The library never fetches on its own — you control allowlists, auth headers, and SSRF policy. Return null to skip an image (falls back to alt text).

Browser or Node · imageResolver
const docx = await convertHtmlToDocx(html, {
  imageResolver: async (src) => {
    // YOUR policy: allowlist hosts, block private IPs, add auth…
    const url = new URL(src, window.location.href);
    if (url.hostname !== "cdn.example.com") return null;

    const res = await fetch(src);
    if (!res.ok) return null;

    return {
      data: new Uint8Array(await res.arrayBuffer()),
      type: "png", // png | jpg | gif | bmp
    };
  },
});

See the invoice example for a document with an embedded logo resolved at conversion time.

Node.js — inline styles

The Node entry point returns a Buffer. Best for agent-generated HTML with explicit inline styles — fast (~15–30 ms typical) with no browser dependency.

Node · inline styles
import { writeFile } from "node:fs/promises";
import { convertHtmlToDocx } from "dom-docx";

const html = `
<h1 style="color:#1a1a2e">Quarterly Report</h1>
<p>Revenue grew <strong>12%</strong> year over year.</p>
<ul>
  <li>North America</li>
  <li>EMEA</li>
</ul>
`;

const docx = await convertHtmlToDocx(html);
await writeFile("output.docx", docx);

Node.js — computed styles

On Node, styleSource: "computed" renders the fragment in headless Chromium via Playwright, snapshots computed styles, then converts. Slower than inline — reuse a browser instance in hot loops.

Prerequisite: Playwright is an optional peer dependency — it is not installed by npm install dom-docx. On the machine running Node, add it and its Chromium once:
npm install playwright && npx playwright install chromium

Node · computed styles
import { convertHtmlToDocx } from "dom-docx";

const html = `
<style>
  .hero { background: #eaeaea; padding: 10px 16px; }
  .hero h1 { color: #1a1a2e; margin: 0; }
</style>
<div class="hero">
  <h1>Title</h1>
</div>
`;

// launches headless Chromium via Playwright, snapshots computed styles, then converts
const docx = await convertHtmlToDocx(html, { styleSource: "computed" });

Reuse Playwright across many conversions instead of launching Chromium per call:

Node · reuse browser
import { chromium } from "playwright";
import { convertHtmlToDocx } from "dom-docx";

const browser = await chromium.launch();
try {
  for (const html of fragments) {
    const docx = await convertHtmlToDocx(html, {
      styleSource: "computed",
      browser, // reuse browser — avoids cold launch, improves throughput
    });
    // write docx…
  }
} finally {
  await browser.close();
}

Document options

Page layout, fonts, metadata, headers/footers, and locale are all optional. Omitted sides default to sensible values (e.g. margins default to 1″ per side).

Node or browser · ConvertOptions
import { convertHtmlToDocx } from "dom-docx";

const docx = await convertHtmlToDocx(html, {
  pageSize: "a4",                    // "letter" | "a4" | { width, height } in inches
  orientation: "landscape",          // "portrait" | "landscape"
  margins: { top: 0.75, bottom: 0.75 }, // inches; left/right default to 1
  defaultFont: { family: "Georgia", sizePt: 11 },
  metadata: {
    title: "Q3 Report",
    creator: "Finance",
    keywords: ["revenue", "q3"],
  },
  headerHtml: "<p style='font-size:12px;color:#666'>Confidential</p>",
  footerHtml: "<p style='font-size:12px'>© 2026 ACME</p>",
  pageNumber: true,                // centered "Page N" in footer
  lang: "en-US",
  direction: "ltr",                  // "rtl" for right-to-left
});

Script tag (no bundler)

The npm package includes a prebuilt IIFE that exposes window.domDocx (from dist/browser/dom-docx.browser.js). Load it from a CDN or copy it from node_modules after npm install dom-docx.

HTML · script tag
<script src="https://unpkg.com/dom-docx/dist/browser/dom-docx.browser.js"></script>
<script>
  const html = "<h1 style='color:#1a1a2e'>Hello</h1>";
  const blob = await domDocx.convertHtmlToDocx(html);
  // download blob…
</script>

More reference