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.
Engineering
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
pptxgenjsis a low-level JavaScript library for generating.pptxfiles. 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-pptxis a higher-level library that takes a DOM element (or a CSS selector) and emits an editable.pptxslide that visually matches the rendered HTML — gradients, shadows, rounded images, SVG charts. It is built on top ofpptxgenjsand runs entirely client-side.- WebToSlides is the hosted alternative: paste a URL or HTML, get an editable
.pptxback. No fonts to embed, no CORS to negotiate, nohtml2canvasto 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
html2canvasquirks, 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:
- Font CORS. Auto-embedding only works when the font's CSS and binary are served with
Access-Control-Allow-Origin: *. Google Fonts requirescrossorigin="anonymous"on the<link>tag. Without it, PowerPoint silently falls back to Arial. - Image CORS.
<img>tags going through the rounding/masking engine need CORS headers too. Self-hosted or proxy-cached images are the safe path. - Layout system. The library does not interpret flexbox or grid. It measures the final
x, y, width, heightafter 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 callexportToPptx.
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
- Read the HTML to PPTX complete guide for the full taxonomy of conversion approaches.
- See HTML to PPTX vs. screenshot decks for why editable output is worth the effort.
- If you want a hosted converter, try HTML to PPTX or URL to PowerPoint — paste, review the outline, download.
Try WebToSlides free
Convert any webpage into an editable PowerPoint deck — no credit card required.
Convert a webpage