| name | description |
|---|---|
html-to-png |
Use this skill whenever you want to convert an HTML, JavaScript, or CSS diagram, visualization, or UI component into a transparent PNG image. Triggers include any mention of 'export to PNG', 'transparent PNG', 'save as image', 'screenshot of HTML', 'render to PNG', or requests to turn web-based visuals (diagrams, charts, infographics, architecture drawings, flowcharts, etc.) into downloadable image files. Also use when you have an existing HTML file and want a static image version. Do NOT use for PDF generation, video/GIF recording, or non-image export formats. |
This skill converts HTML/CSS/JS content into high-resolution transparent PNG images using Puppeteer and headless Chrome. It handles font loading, CSS animations (waiting for them to settle), retina-quality rendering, and transparent backgrounds.
- You have an HTML file or inline HTML/CSS/JS and want a PNG
- You need a "transparent PNG", "export to image", or "render as PNG"
- You created a diagram, chart, infographic, or visualization in HTML and want an image file
- You want a high-resolution image suitable for slides, documents, or print
- Node.js (v16 or later)
- Chrome/Chromium installed on your system
Before rendering, ensure the HTML has a transparent background. If the HTML has a solid background on body or the root container, change it:
/* BEFORE — opaque */
body { background: #0a0c10; }
/* AFTER — transparent */
body { background: transparent; }Important: Only make body (or html) transparent. Inner elements should keep their backgrounds so card/panel styling is preserved. The goal is that the overall canvas is transparent while the content floats on top.
If the HTML was originally designed with a dark background, the text and element colors are probably light. These will still look correct on any dark surface the PNG is placed on. If you need it to work on light backgrounds too, adjust text colors accordingly.
Option A: Full Puppeteer (downloads Chromium automatically)
npm install puppeteerOption B: Puppeteer-core (use existing Chrome installation)
npm install puppeteer-coreIf using Option B, you must specify the Chrome executable path in the script (see Step 3).
Create a file named render_png.js with the following content:
const puppeteer = require('puppeteer'); // or 'puppeteer-core'
const path = require('path');
const [,, inputHtml, outputPng, width = 900, height = 900, scale = 2, waitMs = 2500] = process.argv;
if (!inputHtml || !outputPng) {
console.error('Usage: node render_png.js <input.html> <output.png> [width] [height] [scale] [wait_ms]');
process.exit(1);
}
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
// Uncomment and set path if using puppeteer-core:
// executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', // Windows
// executablePath: '/usr/bin/google-chrome', // Linux
// executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', // macOS
});
const page = await browser.newPage();
await page.setViewport({
width: parseInt(width),
height: parseInt(height),
deviceScaleFactor: parseInt(scale),
});
const filePath = path.resolve(inputHtml);
await page.goto(`file://${filePath}`, { waitUntil: 'networkidle0' });
await new Promise(r => setTimeout(r, parseInt(waitMs)));
await page.screenshot({
path: outputPng,
omitBackground: true, // Enables transparency
fullPage: false,
});
await browser.close();
console.log(`PNG saved to: ${outputPng}`);
})();node render_png.js <input.html> <output.png> [width] [height] [scale] [wait_ms]Parameters:
| Param | Default | Description |
|---|---|---|
input.html |
(required) | Path to the HTML file |
output.png |
(required) | Path for the output PNG |
width |
900 |
Viewport width in pixels |
height |
900 |
Viewport height in pixels |
scale |
2 |
Device scale factor (2 = retina/2x resolution) |
wait_ms |
2500 |
Milliseconds to wait after page load for animations to settle |
Examples:
# Default: 900×900 at 2x (outputs 1800×1800 PNG)
node render_png.js diagram.html diagram.png
# Wide format for presentations (1920×1080 at 2x → 3840×2160)
node render_png.js slide.html slide.png 1920 1080 2 1000
# Square social media image at 3x
node render_png.js card.html card.png 1080 1080 3 2000
# Fast render, no animations to wait for
node render_png.js simple.html simple.png 800 600 2 100The output PNG will be saved to the specified output path.
Here's the full sequence for converting an existing HTML diagram:
# 1. Install puppeteer
npm install puppeteer
# 2. Create render_png.js (see Step 3 above)
# 3. If the HTML needs background made transparent, edit the body background in the HTML file
# 4. Render
node render_png.js my-diagram.html my-diagram.png 900 900 2 2500
# 5. Verify (Linux/macOS)
file my-diagram.png # Should show: PNG image data, RGBA
# 5. Verify (Windows PowerShell)
# Check file exists and open to verify
Get-Item my-diagram.pngSet wait_ms high enough for all CSS animations and transitions to complete. Inspect the CSS — find the longest animation-duration + animation-delay and add 500ms buffer. Default 2500ms handles most cases.
The script uses waitUntil: 'networkidle0' which waits for all network requests (including font loads) to finish. If fonts still don't render, increase wait_ms.
The script clips to the viewport dimensions. Either:
- Increase
width/heightto fit all content, or - Redesign the HTML to fit the target dimensions
If you explicitly want a solid background, keep the body background color in the HTML. Then set omitBackground: false in the script, or simply leave the background — Puppeteer's omitBackground: true only removes the default white background; if the HTML sets its own background color, that color renders into the PNG.
To export an existing HTML file:
- Copy the HTML content into a file (e.g.,
artifact.html) - Modify the body background to transparent if needed
- Run the render script
- Use the output PNG as needed
| Use Case | Width | Height | Scale | Result |
|---|---|---|---|---|
| Slide (16:9) | 1920 | 1080 | 2 | 3840×2160 |
| Slide (4:3) | 1440 | 1080 | 2 | 2880×2160 |
| Square diagram | 900 | 900 | 2 | 1800×1800 |
| Social media | 1080 | 1080 | 2 | 2160×2160 |
| Banner | 1200 | 630 | 2 | 2400×1260 |
| Icon/Badge | 256 | 256 | 3 | 768×768 |
| Problem | Solution |
|---|---|
| Chrome not found | Set executablePath in the script to your Chrome installation path |
| Chrome crashes / Target closed | Add --single-process --no-zygote to the args array |
| Blank/white PNG | HTML body background is white; make it transparent |
| Fonts not loading | Increase wait_ms or check network access to font CDN |
| Content cut off | Increase width and/or height |
| Blurry output | Increase scale (2 is standard retina, 3 for extra crisp) |
| Script hangs | Reduce wait_ms; check for infinite JS animations blocking idle |
puppeteer not found |
Run npm install puppeteer in your project directory |
| Platform | Typical Chrome Path |
|---|---|
| Windows | C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe |
| macOS | /Applications/Google Chrome.app/Contents/MacOS/Google Chrome |
| Linux | /usr/bin/google-chrome or /usr/bin/chromium-browser |