exportToPDF
The main export function. Pass an HTMLElement and receive a PDFExportResult handle.
import { exportToPDF } from "react-print-pdf";
const result = await exportToPDF(element, options);Signature
function exportToPDF(
element: HTMLElement,
options?: ExportOptions,
): Promise<PDFExportResult>;element must be a mounted DOM node. In React, pass ref.current.
Options
format
Page size. Presets are in millimetres internally. A tuple is [widthMm, heightMm].
format: "A4"
format: "Letter"
format: [210, 297]Default: "A4".
orientation
orientation: "portrait" | "landscape"Default: "portrait".
margin
Margins accept CSS-like units. Numbers are treated as CSS pixels.
margin: "20mm"
margin: "1in"
margin: 24 // 24 CSS px
margin: { top: "18mm", right: "16mm", bottom: "22mm", left: "16mm" }Supported units: mm, cm, in, px, pt. Unitless strings are treated as pixels.
Default: 0. Set explicitly when you want printable margins. Common choice for documents: "20mm". Headers and footers render inside the top / bottom margin band, so passing margin: 0 together with header / footer will leave the bands no room to draw — set a margin (or accept that the bands won't render).
align
align: "left" | "center" | "right"Horizontal alignment of body content within the page's content area (the area between left and right margins).
"center"(default) — if your DOM is narrower than the content area, the document is centered horizontally. Wider DOM is left-anchored at the left margin so nothing is clipped."left"— always anchor at the left margin (legacy behavior)."right"— anchor at the right margin.
This affects body primitives and repeat bands (e.g. <thead data-print-repeat>), so column headers stay aligned with the rows underneath them across pages.
pageBreak
pageBreak: "auto" | "manual" | "single"| Mode | Behavior |
|---|---|
auto | Break at overflow and at <PageBreak /> markers |
manual | Break only at <PageBreak /> markers |
single | One page sized to the content bounds |
Default: "auto".
header and footer
Render functions called with page context:
header: ({ pageNumber, totalPages }) => (
<div className="flex justify-between text-xs text-gray-500">
<span>Acme Corp</span>
<span>Page {pageNumber} of {totalPages}</span>
</div>
)type PageContext = {
pageNumber: number;
totalPages: number;
};Header/footer bands are rendered once for measurement, then re-rendered per page after total pages are known.
filename
Default filename used by result.save().
filename: "invoice.pdf"title and author
PDF metadata fields:
title: "Invoice #1042"
author: "Acme Corp"onProgress
onProgress?: (stage: ExportStage, pct: number) => void;Stages:
type ExportStage = "prepare" | "walk" | "paginate" | "emit" | "deliver";pct is 0 or 1 for each current stage. The library does not yet stream sub-stage progress.
onPageRendered
onPageRendered?: (pageNumber: number, totalPages: number) => void;Fires once per page in page order, after the page is fully composed but before the document is serialized. Useful for streaming progress at per-page granularity, sending each page off as a thumbnail, or driving an external progress UI. Errors thrown from the hook propagate to the caller of exportToPDF and abort the export.
await exportToPDF(printRef.current, {
onPageRendered: (pageNumber, total) => {
console.log(`rendered ${pageNumber}/${total}`);
},
});debug
debug?: boolean;When true, the emitter draws a thin colored outline around every primitive's bounding box plus a small label in the top-left corner indicating the primitive kind. Useful when chasing a misaligned element or verifying which regions rasterized vs. drew vector. Off by default; ship debug: false to your users.
Color key: blue rect, magenta border, red text, green image, olive raster, orange link, teal softRect / softRectSlice.
Result
type PDFExportResult = {
bytes: () => Uint8Array;
blob: () => Blob;
save: (filename?: string) => void;
preview: () => Window | null;
};Example:
const result = await exportToPDF(printRef.current, {
format: "A4",
margin: "20mm",
filename: "invoice.pdf",
});
result.save();
await uploadPDF(result.blob());