Convert HTML slide decks to editable PowerPoint files using browser-based DOM measurement.
Project description
html-to-pptx
Convert HTML slide decks into editable PowerPoint files.
Unlike screenshot-based approaches that produce flat images, html-to-pptx measures every DOM element in a headless browser and maps it to a native PPTX shape — text boxes you can edit, images you can resize, backgrounds you can restyle. The output is a real presentation, not a picture of one.
Install
pip install html-to-pptx
python -m playwright install chromium
Quick start
CLI
html-to-pptx deck.html deck.pptx
Python
import asyncio
from html_to_pptx import convert
asyncio.run(convert("deck.html", "deck.pptx"))
Two-stage API
For more control, separate the measurement and rendering steps:
import asyncio
from html_to_pptx import extract_measurements, render_pptx
async def main():
# Stage 1: measure DOM elements in a headless browser
measurements = await extract_measurements("deck.html")
# Stage 2: render measurements to python-pptx shapes
prs = render_pptx(measurements)
# Modify the presentation before saving
prs.slides[0].shapes[0].text = "Custom title"
prs.save("deck.pptx")
asyncio.run(main())
HTML format
Your HTML file should contain <section class="slide"> elements at a 1920×1080 canvas:
<!DOCTYPE html>
<html>
<head>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #000; overflow: hidden; }
.slide {
width: 1920px;
height: 1080px;
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: sans-serif;
}
.slide.active { display: flex; }
</style>
</head>
<body>
<section class="slide active" style="background-color: #1e293b;">
<h1 style="font-size: 64px; color: #f8fafc;">Hello World</h1>
</section>
<section class="slide" style="background-color: #ffffff;">
<p style="font-size: 24px; color: #334155;">Second slide</p>
</section>
</body>
</html>
See examples/demo.html for a full five-slide deck.
What gets converted
| HTML feature | PPTX output |
|---|---|
| Text with fonts, colors, weight, style | Editable text boxes with matching font properties |
Mixed inline content (<p>text <strong>bold</strong> more</p>) |
Multi-run paragraphs with per-run styling |
| CSS linear-gradient backgrounds | OOXML gradient fills with angle and stop positions |
Gradient text (-webkit-background-clip: text) |
Gradient text fill (or solid fallback) |
Inline <svg> elements |
Rasterized to PNG via Playwright screenshot |
| Background colors | Solid fills (with alpha transparency) |
Rounded corners (border-radius, including %) |
OOXML adjustment guides on rounded rectangles |
Rounded images (border-radius on <img>) |
Rounded-rect geometry swap on picture shapes |
Base64-embedded images (data:image/...) |
Native picture shapes |
| Borders (with alpha) | Shape outlines with color, width, and opacity |
| Left-border accent bars | Separate narrow rectangle shapes |
text-transform (uppercase, etc.) |
Transformed text content |
| Hyperlinks | Preserved on text runs |
| Ordered/unordered lists | Bullet/number prefixes with marker colors |
CSS ::before/::after pseudo-elements |
Synthetic shapes for decorative accents |
| RTL text direction | Correct paragraph alignment |
<br> tags in inline runs |
Multi-paragraph text frames |
| Element opacity | OOXML alpha on fill colors |
How it works
HTML file
│
▼
┌─────────────────────────┐
│ Headless Chromium │ ← Playwright loads the HTML at 1920×1080
│ (Playwright) │
│ │
│ For each .slide: │
│ • Show slide in isolation│
│ • Clear CSS transforms │
│ • Measure every visible │
│ element recursively: │
│ position, size, color,│
│ font, text, images │
└───────────┬─────────────┘
│
▼
Measurement tree (JSON)
│
▼
┌─────────────────────────┐
│ python-pptx renderer │
│ │
│ For each element: │
│ • Text leaf → text box │
│ • Image → picture shape │
│ • Background → rectangle│
│ • Border → outline/shape│
│ │
│ Coordinates: │
│ CSS px → inches using │
│ 13.333/1920 ratio │
└───────────┬─────────────┘
│
▼
Editable .pptx
Visual comparison tool
Verify conversion quality with side-by-side comparisons:
pip install html-to-pptx[compare]
html-to-pptx-compare deck.html -o results/
This screenshots the original HTML, converts to PPTX, renders the PPTX back to images via LibreOffice, and creates side-by-side comparison PNGs. Requires LibreOffice on PATH.
Output structure:
results/deck/
├── html_slide_0.png # ground truth (HTML screenshot)
├── html_slide_1.png
├── pptx_slide_0.png # converter output (PPTX rendered via LibreOffice)
├── pptx_slide_1.png
├── compare_slide_0.png # side-by-side comparison
├── compare_slide_1.png
└── output.pptx # the generated file
Limitations
- External images are not fetched — use base64
data:URIs for embedded images - CSS
background-image: url(...)on containers is not converted — only<img>tags with base64srcand inline<svg>elements become picture shapes - Radial gradients are not supported — only
linear-gradient - Animations and transitions are not represented in PPTX
- Font availability — the PPTX references font names from the HTML; if those fonts aren't installed on the machine opening the file, PowerPoint will substitute
- Complex CSS layouts (grid, advanced flexbox) are measured as-rendered, but deeply nested layouts may lose some positioning precision
Development
git clone https://github.com/Design-Arena/html-to-pptx.git
cd html-to-pptx
pip install -e ".[dev]"
python -m playwright install chromium
pytest -v
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file html_to_pptx-0.2.0.tar.gz.
File metadata
- Download URL: html_to_pptx-0.2.0.tar.gz
- Upload date:
- Size: 25.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ae6544a1d31b9333804d9483ded873bfe7a63ec054d871d223c0cec6782c3d9
|
|
| MD5 |
5938c5f38bb2a587c55b53777321a7b3
|
|
| BLAKE2b-256 |
7986a7160b61230d9cf932a2cda96b37cafbb33e79039b89390fcf0fbd63f77c
|
Provenance
The following attestation bundles were made for html_to_pptx-0.2.0.tar.gz:
Publisher:
publish.yml on Design-Arena/html-to-pptx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
html_to_pptx-0.2.0.tar.gz -
Subject digest:
2ae6544a1d31b9333804d9483ded873bfe7a63ec054d871d223c0cec6782c3d9 - Sigstore transparency entry: 1906967168
- Sigstore integration time:
-
Permalink:
Design-Arena/html-to-pptx@9c7ebe7cc7127b7fa26d3e9039f0553e51c1a703 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Design-Arena
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9c7ebe7cc7127b7fa26d3e9039f0553e51c1a703 -
Trigger Event:
release
-
Statement type:
File details
Details for the file html_to_pptx-0.2.0-py3-none-any.whl.
File metadata
- Download URL: html_to_pptx-0.2.0-py3-none-any.whl
- Upload date:
- Size: 22.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64379a7e1fb901aff6bd014699fcffd3a168eeaab5c400c3af7eeb4cd906d8d0
|
|
| MD5 |
aab8cad39c82cf77d181e2a02751c98b
|
|
| BLAKE2b-256 |
f31a4651be4d3a83d71b9c63e771cee293af6a357c6c221191ad8ad1b4a4e40c
|
Provenance
The following attestation bundles were made for html_to_pptx-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on Design-Arena/html-to-pptx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
html_to_pptx-0.2.0-py3-none-any.whl -
Subject digest:
64379a7e1fb901aff6bd014699fcffd3a168eeaab5c400c3af7eeb4cd906d8d0 - Sigstore transparency entry: 1906967257
- Sigstore integration time:
-
Permalink:
Design-Arena/html-to-pptx@9c7ebe7cc7127b7fa26d3e9039f0553e51c1a703 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Design-Arena
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9c7ebe7cc7127b7fa26d3e9039f0553e51c1a703 -
Trigger Event:
release
-
Statement type: