Complete guide to using HTML to PDF Generator in your React applications.
npm install @encryptioner/html-to-pdf-generatorThe simplest way to generate PDFs in React:
import { usePDFGenerator } from '@encryptioner/html-to-pdf-generator/react';
export default function Invoice() {
const { targetRef, generatePDF, isGenerating, progress } = usePDFGenerator({
filename: 'invoice.pdf',
format: 'a4',
showPageNumbers: true,
});
return (
<div>
<div ref={targetRef} className="w-[794px] p-8 bg-white">
<h1 className="text-3xl font-bold">Invoice #12345</h1>
<p>Amount: $1,234.56</p>
</div>
<button
onClick={generatePDF}
disabled={isGenerating}
className="px-4 py-2 bg-blue-500 text-white rounded"
>
{isGenerating ? `Generating... ${progress}%` : 'Download PDF'}
</button>
</div>
);
}const { targetRef, generatePDF, isGenerating, progress, error, result } =
usePDFGenerator({
filename: 'document.pdf',
format: 'a4',
});| Property | Type | Description |
|---|---|---|
targetRef |
RefObject<HTMLDivElement> |
Attach to element to convert |
generatePDF() |
() => Promise<void> |
Generate and download PDF |
generateBlob() |
() => Promise<Blob> |
Generate blob without download |
isGenerating |
boolean |
Whether PDF is being generated |
progress |
number |
Current progress (0-100) |
error |
Error | null |
Error if generation failed |
result |
PDFGenerationResult | null |
Result from last generation |
reset() |
() => void |
Reset state |
const pdf = usePDFGenerator({
// Required
filename: 'document.pdf',
// Paper settings
format: 'a4', // 'a4' | 'letter' | 'a3' | 'legal'
orientation: 'portrait', // 'portrait' | 'landscape'
margins: [10, 10, 10, 10], // [top, right, bottom, left] in mm
// Quality
scale: 2, // 1-4, higher = better quality
imageQuality: 0.85, // 0-1 (legacy, use imageOptions instead)
compress: true,
// Image Optimization
imageOptions: {
dpi: 300, // 72 (web), 150 (print), 300 (high-quality)
format: 'jpeg', // 'jpeg' | 'png' | 'webp'
backgroundColor: '#ffffff', // Background for transparent images
optimizeForPrint: true, // Enable print optimizations
interpolate: true, // Image smoothing
quality: 0.92 // Compression quality
},
// Features
showPageNumbers: true,
pageNumberPosition: 'footer', // 'header' | 'footer'
// Callbacks
onProgress: (progress) => console.log(`${progress}%`),
onComplete: (blob) => console.log('Done!', blob),
onError: (error) => console.error('Failed:', error),
});For cases where you can't use refs or need more control:
import { usePDFGeneratorManual } from '@encryptioner/html-to-pdf-generator/react';
export default function FlexiblePDF() {
const { generatePDF, isGenerating, progress } = usePDFGeneratorManual({
filename: 'document.pdf',
});
const handleDownload = () => {
const element = document.getElementById('my-content');
if (element) {
generatePDF(element);
}
};
return (
<div>
<div id="my-content">
<h1>Content</h1>
</div>
<button onClick={handleDownload}>Download</button>
</div>
);
}export default function Report() {
const { targetRef, generatePDF, isGenerating, progress } = usePDFGenerator({
filename: 'report.pdf',
});
return (
<div>
<div ref={targetRef}>{/* Content */}</div>
<button onClick={generatePDF} disabled={isGenerating}>
{isGenerating ? (
<div className="flex items-center gap-2">
<Spinner />
<span>Generating {progress}%</span>
</div>
) : (
'Download PDF'
)}
</button>
</div>
);
}export default function Document() {
const { targetRef, generatePDF, error } = usePDFGenerator({
filename: 'document.pdf',
onError: (err) => {
console.error('PDF generation failed:', err);
toast.error('Failed to generate PDF');
},
});
return (
<div>
<div ref={targetRef}>{/* Content */}</div>
<button onClick={generatePDF}>Download</button>
{error && (
<div className="text-red-500">
Error: {error.message}
</div>
)}
</div>
);
}export default function UploadablePDF() {
const { targetRef, generateBlob, isGenerating } = usePDFGenerator({
filename: 'document.pdf',
});
const handleUpload = async () => {
const blob = await generateBlob();
const formData = new FormData();
formData.append('pdf', blob, 'document.pdf');
await fetch('/api/upload', {
method: 'POST',
body: formData,
});
toast.success('PDF uploaded!');
};
return (
<div>
<div ref={targetRef}>{/* Content */}</div>
<button onClick={handleUpload} disabled={isGenerating}>
Upload PDF
</button>
</div>
);
}export default function MultiPDF() {
const invoice = usePDFGenerator({ filename: 'invoice.pdf' });
const receipt = usePDFGenerator({ filename: 'receipt.pdf' });
return (
<div>
<div ref={invoice.targetRef}>{/* Invoice content */}</div>
<button onClick={invoice.generatePDF}>Download Invoice</button>
<div ref={receipt.targetRef}>{/* Receipt content */}</div>
<button onClick={receipt.generatePDF}>Download Receipt</button>
</div>
);
}import { Progress } from '@/components/ui/progress';
export default function ProgressPDF() {
const { targetRef, generatePDF, isGenerating, progress } = usePDFGenerator({
filename: 'document.pdf',
});
return (
<div>
<div ref={targetRef}>{/* Content */}</div>
{isGenerating && (
<div className="space-y-2">
<Progress value={progress} />
<p className="text-sm text-gray-600">
Generating PDF... {progress}%
</p>
</div>
)}
<button onClick={generatePDF} disabled={isGenerating}>
Download PDF
</button>
</div>
);
}export default function DynamicInvoice() {
const [items, setItems] = useState([
{ name: 'Item 1', price: 100 },
{ name: 'Item 2', price: 200 },
]);
const { targetRef, generatePDF, isGenerating } = usePDFGenerator({
filename: 'invoice.pdf',
showPageNumbers: true,
});
return (
<div>
<div ref={targetRef} className="w-[794px]">
<h1>Invoice</h1>
<table>
<thead>
<tr>
<th>Item</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{items.map((item, i) => (
<tr key={i}>
<td>{item.name}</td>
<td>${item.price}</td>
</tr>
))}
</tbody>
</table>
<p className="font-bold">
Total: ${items.reduce((sum, item) => sum + item.price, 0)}
</p>
</div>
<button onClick={generatePDF}>
{isGenerating ? 'Generating...' : 'Download Invoice'}
</button>
</div>
);
}export default function StyledPDF() {
const { targetRef, generatePDF } = usePDFGenerator({
filename: 'styled-document.pdf',
});
return (
<div>
<div ref={targetRef} className="w-[794px] p-8 bg-gray-50">
<h1 className="text-4xl font-bold text-blue-600 mb-4">
Styled Document
</h1>
<div className="bg-white p-6 rounded-lg shadow-lg">
<p className="text-gray-700 leading-relaxed">
This content uses Tailwind CSS classes that will appear in the PDF.
</p>
</div>
</div>
<button onClick={generatePDF}>Download</button>
</div>
);
}export default function ConditionalPDF() {
const [showDetails, setShowDetails] = useState(false);
const { targetRef, generatePDF } = usePDFGenerator({
filename: 'document.pdf',
});
return (
<div>
<label>
<input
type="checkbox"
checked={showDetails}
onChange={(e) => setShowDetails(e.target.checked)}
/>
Include detailed information in PDF
</label>
<div ref={targetRef}>
<h1>Report</h1>
<p>Summary information...</p>
{showDetails && (
<div>
<h2>Detailed Information</h2>
<p>This only appears if checkbox is checked before generating PDF</p>
</div>
)}
</div>
<button onClick={generatePDF}>Download PDF</button>
</div>
);
}Full TypeScript support with complete type definitions:
import type {
PDFGeneratorOptions,
PDFGenerationResult,
UsePDFGeneratorOptions,
} from '@encryptioner/html-to-pdf-generator/react';
const options: UsePDFGeneratorOptions = {
filename: 'document.pdf',
format: 'a4',
showPageNumbers: true,
};
const {
targetRef,
generatePDF,
isGenerating,
progress,
error,
result,
}: UsePDFGeneratorReturn = usePDFGenerator(options);
// Result type is fully typed
if (result) {
const pageCount: number = result.pageCount;
const fileSize: number = result.fileSize;
const generationTime: number = result.generationTime;
}<div ref={targetRef} className="w-[794px]"> {/* A4 width */}
{/* Content */}
</div><button onClick={generatePDF} disabled={isGenerating}>
{isGenerating ? `${progress}%` : 'Download'}
</button>const pdf = usePDFGenerator({
filename: 'document.pdf',
onError: (err) => {
console.error(err);
toast.error('Failed to generate PDF');
},
});useEffect(() => {
// Ensure images are loaded
const images = Array.from(document.images);
Promise.all(
images.map((img) => {
if (img.complete) return Promise.resolve();
return new Promise((resolve) => {
img.onload = resolve;
img.onerror = resolve;
});
})
);
}, []);const pdf = usePDFGenerator({
filename: 'document.pdf',
scale: 1.5, // Lower for faster generation
compress: true, // Reduce file size
imageQuality: 0.8, // Balance quality/size
});// ❌ Wrong: ref on wrong element
<div>
<div ref={targetRef}>
Content
</div>
</div>
// ✅ Correct
<div ref={targetRef}>
Content
</div>// Ensure CSS is loaded before generating
useEffect(() => {
// Wait for stylesheets
const styleSheets = Array.from(document.styleSheets);
// ... load check
}, []);// Use fixed width matching PDF format
<div ref={targetRef} style={{ width: '794px' }}>
Content
</div>- Image Handling - Basic image handling to DPI control and print quality
- Options Reference - Complete options documentation
- Code Examples - Copy-paste ready samples
- Production Examples - Real-world use cases
- Best Practices - Optimization tips