Common issues and solutions when using the HTML to PDF Generator.
Problem: Generated PDF is blank or missing content.
Solutions:
- Wait for images to load:
// Ensure images are loaded before generating
await new Promise(resolve => {
if (document.readyState === 'complete') {
resolve();
} else {
window.addEventListener('load', resolve);
}
});
await generatePDF(element, 'document.pdf');- Check element visibility:
// Element must be visible in DOM
const element = document.getElementById('content');
console.log('Visible:', element.offsetHeight > 0);- Verify element is in DOM:
const element = document.getElementById('content');
console.log('In DOM:', document.body.contains(element));Problem: Content is truncated or cut off in PDF.
Solutions:
- Use fixed width container:
<div ref={targetRef} style={{ width: '794px' }}>
<!-- A4 width at 96 DPI -->
Content here
</div>- Check for overflow hidden:
/* Avoid overflow: hidden on PDF container */
.pdf-container {
overflow: visible; /* Not hidden */
}- Increase margins if content touches edges:
await generatePDF(element, 'document.pdf', {
margins: [15, 15, 15, 15], // Increase from default [10,10,10,10]
});Problem: CSS styles don't appear in PDF.
Solutions:
- Ensure stylesheets are loaded:
// Wait for stylesheets
await Promise.all(
Array.from(document.styleSheets).map(sheet => {
try {
return sheet.cssRules; // Access to trigger load
} catch (e) {
return Promise.resolve();
}
})
);- Inline critical styles:
<div style="color: red; font-size: 16px;">
Inline styles always work
</div>- Use customCSS option:
await generatePDF(element, 'document.pdf', {
customCSS: `
.important { color: red; }
h1 { font-size: 24px; }
`
});- Check for CORS issues:
// External stylesheets must allow CORS
// Use same-origin stylesheets or enable CORS
Problem: Images missing from PDF.
Solutions:
- Preload images:
const images = Array.from(document.images);
await Promise.all(
images.map(img => {
if (img.complete) return Promise.resolve();
return new Promise(resolve => {
img.onload = resolve;
img.onerror = resolve;
});
})
);- Use data URLs or same-origin images:
<!-- ✅ Works -->
<img src="data:image/png;base64,..." />
<img src="/local/image.png" />
<!-- ❌ May fail due to CORS -->
<img src="https://external-site.com/image.png" />- Enable CORS on server:
// For external images, ensure server sends:
// Access-Control-Allow-Origin: *Problem: SVG elements don't appear or look wrong.
Solutions:
- Enable SVG conversion (default):
await generatePDF(element, 'document.pdf', {
convertSVG: true, // Convert SVGs to images
});- Ensure SVG has explicit dimensions:
<svg width="200" height="200">
<!-- Must have width/height -->
</svg>Problem: CSS background images don't show.
Solution: The library automatically handles background images, but ensure they're accessible:
/* ✅ Works */
.header {
background-image: url('/images/bg.png');
}
/* ❌ May fail (CORS) */
.header {
background-image: url('https://external-site.com/bg.png');
}Problem: Generated PDF has very large file size.
Solutions:
- Enable compression:
await generatePDF(element, 'document.pdf', {
compress: true,
});- Reduce image quality:
await generatePDF(element, 'document.pdf', {
imageQuality: 0.75, // Lower from 0.85
optimizeImages: true,
maxImageWidth: 1200,
});- Lower scale factor:
await generatePDF(element, 'document.pdf', {
scale: 1.5, // Lower from 2
});Problem: PDF looks blurry or pixelated.
Solutions:
- Increase scale factor:
await generatePDF(element, 'document.pdf', {
scale: 3, // Higher quality (slower)
});- Increase image quality:
await generatePDF(element, 'document.pdf', {
imageQuality: 0.95, // Higher quality
});- Use vector graphics where possible:
<!-- SVGs scale better than raster images -->
<svg>...</svg>Problem: PDF generation is very slow.
Solutions:
- Reduce scale:
await generatePDF(element, 'document.pdf', {
scale: 1.5, // Faster than 2 or 3
});- Optimize images beforehand:
await generatePDF(element, 'document.pdf', {
optimizeImages: true,
maxImageWidth: 1200,
});- Simplify complex CSS:
/* Avoid expensive effects */
.element {
/* ❌ Slow */
box-shadow: 0 0 100px rgba(0,0,0,0.5);
filter: blur(10px);
/* ✅ Fast */
border: 1px solid #ccc;
}Problem: Browser becomes unresponsive.
Solutions:
- Show progress indicator:
await generatePDF(element, 'document.pdf', {
onProgress: (progress) => {
updateUI(`Generating... ${progress}%`);
},
});- Split large documents:
// Use batch generation for very large docs
import { generateBatchPDF } from '@encryptioner/html-to-pdf-generator';
const items = [
{ content: section1, pageCount: 5 },
{ content: section2, pageCount: 3 },
];
await generateBatchPDF(items, 'large-doc.pdf');Problem: targetRef.current is null.
Solutions:
- Attach ref correctly:
// ✅ Correct
<div ref={targetRef}>Content</div>
// ❌ Wrong
<div><div ref={targetRef}>Content</div></div>- Wait for component to mount:
useEffect(() => {
console.log('Ref ready:', targetRef.current);
}, []);Problem: ESLint warns about missing dependencies.
Solution:
const { generatePDF } = usePDFGenerator({
filename: 'document.pdf',
});
// generatePDF is stable, safe to use in useEffect
useEffect(() => {
// Auto-generate on mount
generatePDF();
}, [generatePDF]); // Safe to includeProblem: targetRef not attaching in Vue.
Solution:
<script setup>
const { targetRef, generatePDF } = usePDFGenerator({
filename: 'document.pdf',
});
</script>
<template>
<!-- Use ref attribute directly -->
<div ref="targetRef">Content</div>
</template>Problem: Error "document is not defined" in Next.js.
Solution:
'use client'; // Add to top of file
import { usePDFGenerator } from '@encryptioner/html-to-pdf-generator/react';
export default function Page() {
// Now works in client component
}Problem: OKLCH colors appear black or incorrect.
Solution: The library uses html2canvas-pro with native OKLCH support. If issues persist:
// Manually convert if needed
import { convertOklchInElement } from '@encryptioner/html-to-pdf-generator';
const element = document.getElementById('content');
convertOklchInElement(element);
await generatePDF(element, 'document.pdf');Problem: Tailwind CSS colors don't match.
Solution: Ensure Tailwind CSS is loaded before generation:
// Wait for Tailwind to initialize
await new Promise(resolve => setTimeout(resolve, 100));
await generatePDF(element, 'document.pdf');Problem: Headers don't repeat on each page.
Solutions:
- Enable header repetition (default):
await generatePDF(element, 'document.pdf', {
repeatTableHeaders: true,
});- Use proper table structure:
<table>
<thead> <!-- Must use thead -->
<tr><th>Header</th></tr>
</thead>
<tbody>
<tr><td>Data</td></tr>
</tbody>
</table>Problem: Table rows are cut in half between pages.
Solution:
await generatePDF(element, 'document.pdf', {
avoidTableRowSplit: true, // Enabled by default
});Problem: CORS error when converting canvas.
Solutions:
- Use same-origin images
- Enable CORS on image server
- Use data URLs for images
Problem: Element doesn't exist when generating.
Solution:
const element = document.getElementById('content');
if (!element) {
console.error('Element not found!');
return;
}
await generatePDF(element, 'document.pdf');Problem: Browser runs out of memory for very large PDFs.
Solutions:
- Reduce scale:
scale: 1 // Minimum scale- Split into smaller PDFs:
// Generate separately and combine- Optimize images:
optimizeImages: true,
maxImageWidth: 800,Still stuck? Here's how to get help:
See Examples for working code samples.
await generatePDF(element, 'document.pdf', {
onProgress: (p) => console.log(`Progress: ${p}%`),
onError: (e) => console.error('Error:', e),
onComplete: (b) => console.log('Success:', b),
});Isolate the issue:
<!DOCTYPE html>
<html>
<body>
<div id="content">
<h1>Test</h1>
</div>
<button onclick="test()">Generate</button>
<script type="module">
import { generatePDF } from '@encryptioner/html-to-pdf-generator';
window.test = async () => {
const el = document.getElementById('content');
await generatePDF(el, 'test.pdf');
};
</script>
</body>
</html>If you've found a bug:
- Check existing issues
- Create minimal reproduction
- Open new issue with:
- Browser and version
- Code sample
- Expected vs actual behavior
- Error messages
- Best Practices - Optimize your PDFs
- Options Reference - Complete options documentation
- Code Examples - Copy-paste ready samples
- Getting Started - Quick start guide