HTML to Image
Screenshot any HTML snippet as a PNG image.
HTML to Image rasterizes an HTML snippet into a downloadable PNG — "Convert HTML and CSS code into downloadable images." The "HTML Code" textarea arrives prefilled with a gradient "Hello World" demo div (placeholder "Enter HTML code..."), and "Width (px)" / "Height (px)" sliders (100–2000, with editable number inputs) plus a "Background" color (default #ffffff) size the full capture frame. A "Transparent background" checkbox (default off) swaps the fill for a fully transparent PNG. "Render to Image" ("Rendering...") produces a PNG preview with a "File Size" stat, then "Download" saves html-screenshot.png.
Rendering uses html2canvas locally inside a hidden same-origin iframe (srcdoc) so host Tailwind v4 oklch()/color-mix() colors never reach html2canvas 1.4.1's color parser — without isolation it throws "Attempting to parse an unsupported color function \\"oklch\\"" and the page toasts a render error. Width/Height always define the full output frame: the PNG is never cropped to content, so empty background padding is included. The iframe uses the chosen backgroundColor behind the content, is filled with your markup, captured, and removed in a finally block even on failure. Nothing is sent to a server — though external <img src=\"https://…\"> URLs inside your HTML may be fetched by the browser (useCORS: true), so prefer data URLs for fully offline renders. Empty input toasts \"Please enter some HTML\".
How it works
lib/imageHtmlToImage.ts lazy loads html2canvas, builds a hidden fixed iframe (srcdoc, no site CSS) sized to width×height with backgroundColor (or transparent when the checkbox is on), writes the HTML into that isolated document, and calls html2canvas(documentElement, { width, height, windowWidth, windowHeight, backgroundColor, useCORS: true, logging: false }). The canvas is never cropped — the full Width×Height frame is exported. Isolation is required because html2canvas always parses ownerDocument html/body backgrounds, and Tailwind v4 sets those to oklch() which the parser rejects. The result exports via toBlob('image/png') as html-screenshot.png with width/height equal to Width/Height, and the iframe is removed in a finally block even when rendering fails. The lazy import keeps the heavy library out of the route chunk so local and production builds behave the same. Render failures surface the real Error.message in the toast. Redux serializable ignores: imageHtmlToImageResultSet and imageHtmlToImage.result (File in result).
The Zod htmlToImageSchema covers only width/height int 100–4000 (defaults 800/600), backgroundColor, and transparent boolean (default false); HTML lives in the textarea state outside the form, and the page sliders cap at 2000. Width/Height are the full output frame size. State lives in Redux htmlToImageSlice (result, isProcessing). html2canvas is a bundled npm dependency loaded on demand: no network of its own and no AI, but useCORS means caller-authored external image URLs may load during capture.
Tailwind v4 is not broken for this tool — the capture iframe is deliberately free of globals.css so oklch theme tokens cannot crash html2canvas. The submit button gradient (bg-linear-to-r + color-mix) only styles the button and does not participate in the capture.
How to use
- Edit the prefilled HTML (or paste your snippet) in the "HTML Code" textarea.
- Set "Width (px)" and "Height (px)" with the sliders or type exact pixels in the number fields (100–2000; schema allows up to 4000) — these are the full PNG frame size.
- Pick the "Background" color (default #ffffff), or check "Transparent background" for a PNG with no fill behind the content.
- Click "Render to Image" — empty input raises the toast "Please enter some HTML".
- Review the PNG preview (full Width×Height frame) and the "File Size" stat.
- Click "Download" (saves html-screenshot.png) or "Start Over".
Tips
- Inline styles and simple CSS work best — html2canvas does not execute JavaScript and supports only a subset of CSS.
- External <img src="https://…"> references may trigger browser fetches (useCORS) — prefer data URLs for fully offline renders.
- The off-screen capture iframe is removed after render even on failure (finally block), so no stray DOM lingers.
- Width/Height sliders stop at 2000 though the schema allows 4000 — larger sizes need a schema-level change.
- The submit button uses the shared Button component; extra gradient classes merge via cn (tailwind-merge) and do not block clicks. Render errors show the underlying message (for example oklch parse failures if isolation is ever removed).
HTML to Image FAQ
Is my HTML sent to a server?
No — html2canvas renders locally; only external resources you reference in the HTML may load.
What file is produced?
A PNG named html-screenshot.png at the full Width×Height frame size. With "Transparent background" checked the PNG has no fill behind the content.
Does it run JavaScript in the HTML?
No — html2canvas rasterizes DOM/CSS without executing scripts.
Why does unused background show in the PNG?
The full Width×Height frame is always kept (no crop to content). Empty area uses the Background color, or stays transparent if that checkbox is on.
Can I capture the live page UI?
No — only the HTML string you enter in the textarea is rendered.
Credits
- html2canvas — DOM/CSS rasterizer used in lib/imageHtmlToImage.ts