html-to-image Reference
Capture DOM elements as PNG, JPEG, SVG, or Blob outputs for dashboards, cards, certificates, and shareable graphics.
Imports and setup
import { Download } from "lucide-react";
export default function App() {
const cardRef = React.useRef<HTMLDivElement>(null);
const { download } = useDownload();
const [exporting, setExporting] = React.useState(false);
const handleExport = async () => {
if (!cardRef.current) return;
setExporting(true);
try {
const dataUrl = await toPng(cardRef.current, {
pixelRatio: 2,
backgroundColor: "#ffffff",
});
download(dataUrl, "summary.png");
} finally {
setExporting(false);
}
};
return (
<div>
<div ref={cardRef}>
<div>
<h3>Weekly Summary</h3>
</div>
<div>
<p className="text-2xl font-bold">127 tasks completed</p>
<p className="text-muted-foreground">Up 12% from last week</p>
</div>
</div>
<button onClick={handleExport} disabled={exporting}>
{exporting ? <span className="inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" /> : <Download className="h-4 w-4" />}
Export as PNG
</button>
</div>
);
}
JPEG and Blob exports
Use JPEG for photo-heavy content and set a white background because JPEG does not preserve transparency.
const dataUrl = await toJpeg(ref.current, {
quality: 0.92,
backgroundColor: "#ffffff",
});
download(dataUrl, "export.jpeg");
Use toBlob() for a memory-efficient download path, especially for large captures.
const blob = await toBlob(ref.current, { pixelRatio: 2 });
if (blob) {
download(blob, "capture.png");
}
Filtering controls
Exclude buttons, toolbars, and other interactive controls with the filter option and a data-* attribute.
const dataUrl = await toPng(ref.current, {
filter: (node) => {
if (node instanceof HTMLElement && node.dataset.excludeExport) {
return false;
}
return true;
},
});
<div ref={ref} className="rounded-lg bg-card p-4">
<h2 className="text-xl font-bold">My Report</h2>
<p>This content will be exported.</p>
<div data-exclude-export="true">
<button onClick={handleExport}>Export</button>
</div>
</div>
Best practices
Use pixelRatio: 2 for crisp exports, set backgroundColor for transparent or JPEG exports, prefer toBlob() with useDownload for large captures, filter out controls with data-* attributes, show a loading state while capturing, and wrap the target in a container with explicit background and padding so the exported image looks complete.