WebToSlides
All posts
Developers· 6 min read

dom-to-pptx and PptxGenJS: client-side HTML to editable PowerPoint, explained

dom-to-pptx is a new client-side library that turns any HTML element into a fully editable .pptx, built on top of PptxGenJS. Here's what each one does, where they fit, and when to reach for a hosted alternative instead.

If you have spent any time looking for a way to turn a rendered webpage or a React component into a real, editable PowerPoint file, you have probably hit two npm packages: pptxgenjs and the much newer dom-to-pptx. They solve overlapping problems but at very different layers. This post explains what each one does, the dependency graph behind dom-to-pptx, and when a hosted converter like WebToSlides is the better trade-off.

TL;DR

  • pptxgenjs is a low-level JavaScript library for generating .pptx files. You describe slides, shapes, text, charts, and tables in code; it writes a valid Office Open XML archive. Works in Node.js and the browser.
  • dom-to-pptx is a higher-level library that takes a DOM element (or a CSS selector) and emits an editable .pptx slide that visually matches the rendered HTML — gradients, shadows, rounded images, SVG charts. It is built on top of pptxgenjs and runs entirely client-side.
  • WebToSlides is the hosted alternative: paste a URL or HTML, get an editable .pptx back. No fonts to embed, no CORS to negotiate, no html2canvas to ship in your bundle.

What is PptxGenJS?

pptxgenjs is the de-facto JavaScript library for writing PowerPoint files. You instantiate a presentation, add slides, and place shapes:

import PptxGenJS from "pptxgenjs";

const pptx = new PptxGenJS();
const slide = pptx.addSlide();
slide.addText("Quarterly review", { x: 1, y: 1, fontSize: 32, bold: true });
slide.addText("Revenue grew 24% YoY", { x: 1, y: 2, fontSize: 18 });
await pptx.writeFile({ fileName: "review.pptx" });

Output is a real .pptx — Office Open XML, ISO/IEC 29500 — that opens editable in PowerPoint, Keynote, LibreOffice Impress, and Google Slides (via PPTX import).

The trade-off is that pptxgenjs is a drawing API, not a layout engine. You give it coordinates in inches; it places shapes. There is no concept of flexbox, grid, or "render this <div> with its computed styles." If your slides come from a designer's HTML mock, you have to translate every box, font size, and colour by hand.

What is dom-to-pptx?

dom-to-pptx is a brand-new (April 2026) client-side library that closes that gap. Instead of writing slide code, you point it at a DOM element:

import { exportToPptx } from "dom-to-pptx";

await exportToPptx("#slide-container", {
  fileName: "deck.pptx",
});

Under the hood it walks the DOM, reads each element's computed styles, and emits the equivalent native PowerPoint primitives via pptxgenjs. The maintainer describes it as a "Coordinate Scraper & Style Engine": it does not parse your CSS — it measures the final rendered position and style of every node and maps it to a PowerPoint shape.

What it preserves out of the box (per the v1.1.7 README):

  • CSS gradients (linear, multi-stop, with angles)
  • Box shadows (translated from Cartesian to PowerPoint's polar system)
  • Rounded images (anti-halo masking via off-screen canvas)
  • filter: blur() → PowerPoint soft-edge effects
  • SVGs as editable vectors (with svgAsVector: true)
  • Auto font detection and embedding (Google Fonts, local fonts)
  • Multi-slide export from an array of elements

The dependency tree

dom-to-pptx is a thin orchestration layer over a stack of well-known libraries:

Dependency Role
pptxgenjs Writes the underlying .pptx (DrawingML)
html2canvas Captures fallback raster snapshots of complex regions
fonteditor-core Parses font binaries for embedding
opentype.js Reads OpenType/TrueType fonts
jszip Builds the .pptx ZIP container
pako DEFLATE compression for the ZIP parts

The combination is what enables high-fidelity, editable output without a server. The cost is a ~3.6 MB unpacked install footprint and a runtime that needs a real browser DOM (window, canvas, font CSS).

When to use which

Reach for pptxgenjs when

  • You are generating decks programmatically from structured data — a CSV, a database row, an API response.
  • You want full control over slide layout in code.
  • You are running in Node.js (server-side jobs, cron, Lambda).
  • Bundle size matters and you do not need DOM-to-shape mapping.

Reach for dom-to-pptx when

  • You already have rendered HTML in the browser (a React/Vue/Svelte component, a dashboard, a chart) and want a PPTX that looks like it.
  • You want gradients, shadows, rounded images, and SVG charts to come through editable.
  • You can afford a few megabytes of client-side dependencies and you control the page (so you can fix CORS on fonts and images).

Reach for WebToSlides when

  • The source is a URL or pasted HTML and you do not want to host a renderer.
  • You need batch conversion of many URLs in one job.
  • You want native shapes (titles, bullets, tables, code blocks) rather than visual fidelity to a specific design.
  • You do not want to maintain html2canvas quirks, font CORS workarounds, or a 3.6 MB client bundle.

Gotchas to know up front

If you go the dom-to-pptx route, three things will bite first-time users:

  1. Font CORS. Auto-embedding only works when the font's CSS and binary are served with Access-Control-Allow-Origin: *. Google Fonts requires crossorigin="anonymous" on the <link> tag. Without it, PowerPoint silently falls back to Arial.
  2. Image CORS. <img> tags going through the rounding/masking engine need CORS headers too. Self-hosted or proxy-cached images are the safe path.
  3. Layout system. The library does not interpret flexbox or grid. It measures the final x, y, width, height after the browser has laid the page out, then places shapes absolutely. That means your slide must be visible (or off-screen but rendered) when you call exportToPptx.

Production tip: build slide containers at 1920x1080 and let the library scale them down to the standard 16:9 PPTX size. That gives you predictable text sizing across machines.

What this means for the JavaScript ecosystem

Until now, the JavaScript story for HTML → editable PPTX was either "use pptxgenjs and rebuild the layout in code" or "screenshot the page and paste it into a slide" (which is not editable at all). dom-to-pptx is the first credible client-side bridge between rendered HTML and an editable .pptx. That matters for:

  • Dashboards that need to ship a weekly snapshot deck
  • Reporting tools where every chart already lives in the DOM
  • Slide-builder products that want a "Download as PowerPoint" button without a server round-trip

It does not replace a hosted converter for the URL-in / PPTX-out workflow — that is what WebToSlides is for, and the trade-offs are different (server-side fetch, sanitisation, batch jobs, no client bundle cost). But for "I have HTML and I want a PPTX, in the browser, today," dom-to-pptx plus its pptxgenjs foundation is the new default worth knowing about.

Next steps

#dom-to-pptx#pptxgenjs#html to pptx#javascript#client-side

Try WebToSlides free

Convert any webpage into an editable PowerPoint deck — no credit card required.

Convert a webpage