Learn to create PDF documents dynamically using JavaScript and the jsPDF library. This practical skill is useful for generating reports, invoices, certificates, and other documents in web applications.
PDF (Portable Document Format) is a universal file format that preserves document formatting across different platforms and devices. Generating PDFs programmatically in web applications enables users to download, share, and print documents with consistent formatting.
Client-Side Processing: JavaScript PDF generation happens entirely in the browser, reducing server load and eliminating the need for backend PDF generation services.
Real-Time Document Creation: Users can generate customized documents based on their input, such as filled forms, personalized reports, or dynamic certificates.
Offline Capability: Once the library is loaded, PDF generation works offline, making it suitable for applications that need to function without internet connectivity.
Cost Efficiency: Client-side generation reduces infrastructure costs associated with server-side PDF processing and storage.
Reports and Analytics: Generate business reports, sales summaries, and analytical charts as downloadable PDF documents.
Invoices and Receipts: Create professional invoices, receipts, and billing statements for e-commerce applications.
Certificates and Badges: Generate completion certificates, achievement badges, and award documents for educational platforms.
Forms and Documentation: Convert web forms into PDF submissions, create user manuals, or generate policy documents.
Tickets and Passes: Create event tickets, boarding passes, or admission passes with QR codes and barcodes.
jsPDF is a popular open-source JavaScript library that enables PDF generation directly in the browser. It provides a comprehensive API for creating, formatting, and manipulating PDF documents without requiring server-side processing.
Cross-Browser Compatibility: Works consistently across modern browsers including Chrome, Firefox, Safari, and Edge.
Rich Content Support: Supports text, images, shapes, tables, and complex formatting options.
Multiple Output Formats: Can save PDFs as downloadable files, display them in browser windows, or convert them to data URLs.
Extensible Architecture: Supports plugins and extensions for additional functionality like HTML-to-PDF conversion.
Font Support: Includes built-in fonts and supports custom font embedding for multilingual documents.
CDN Installation: Quick setup for simple projects and prototyping.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
Package Manager Installation: Recommended for production applications.
npm install jspdf
Module Import: Modern ES6 module import syntax.
import { jsPDF } from 'jspdf';
PDF documents created with jsPDF follow a structured format consisting of pages, content streams, and metadata. Understanding this structure helps in creating well-organized documents.
Pages: PDFs can contain multiple pages, each with specified dimensions and orientation.
Content: Text, images, and graphics are positioned using coordinate systems with precise measurements.
Metadata: Document properties like title, author, creation date, and keywords can be embedded.
The first step in PDF generation is creating a new jsPDF instance with desired configuration options.
import { jsPDF } from 'jspdf';
// Create a new PDF document
const doc = new jsPDF();
// Create PDF with specific orientation and unit
const docLandscape = new jsPDF('landscape', 'mm', 'a4');
// Create PDF with custom dimensions
const docCustom = new jsPDF({
orientation: 'portrait',
unit: 'mm',
format: [210, 297] // Custom size in mm
});
jsPDF uses a coordinate system where the origin (0,0) is at the top-left corner of the page. X-coordinates increase horizontally to the right, and Y-coordinates increase vertically downward.
Units: The default unit is millimeters (mm), but you can use points (pt), inches (in), or other units.
Page Boundaries: Be aware of page margins and printable areas to avoid content being cut off.
Positioning: Precise positioning is crucial for professional-looking documents.
Text is the most common content type in PDFs. jsPDF provides various methods for adding and formatting text.
// Basic text addition
doc.text('Hello World!', 20, 20);
// Text with font settings
doc.setFontSize(16);
doc.setFont('helvetica', 'bold');
doc.text('Document Title', 20, 30);
// Multi-line text
const lines = doc.splitTextToSize('This is a long text that will be automatically wrapped to fit within the specified width.', 180);
doc.text(lines, 20, 50);
jsPDF supports various fonts and text formatting options to create visually appealing documents.
Built-in Fonts: Includes standard fonts like Helvetica, Times, and Courier in normal, bold, italic, and bold-italic variants.
Font Sizes: Text size can be adjusted using setFontSize() method.
Text Alignment: Control text alignment for better document layout.
// Font configuration
doc.setFont('times', 'italic');
doc.setFontSize(12);
doc.text('Italic Times Text', 20, 70);
// Text alignment
doc.text('Left aligned', 20, 80, { align: 'left' });
doc.text('Center aligned', 105, 80, { align: 'center' });
doc.text('Right aligned', 190, 80, { align: 'right' });
Images enhance PDF documents by providing visual context and breaking up text-heavy content. jsPDF supports various image formats and positioning options.
// Add image from URL
doc.addImage('https://example.com/image.jpg', 'JPEG', 20, 100, 50, 50);
// Add image from file input
const fileInput = document.getElementById('imageInput');
const file = fileInput.files[0];
const reader = new FileReader();
reader.onload = function(e) {
doc.addImage(e.target.result, 'PNG', 20, 100, 60, 60);
};
reader.readAsDataURL(file);
Geometric shapes add visual interest and help organize information in PDF documents.
// Draw rectangles
doc.setFillColor(200, 200, 200);
doc.rect(20, 120, 50, 30, 'F'); // Filled rectangle
doc.rect(80, 120, 50, 30, 'D'); // Drawn rectangle
// Draw circles
doc.circle(150, 135, 15, 'D');
// Draw lines
doc.setDrawColor(0, 0, 255);
doc.setLineWidth(2);
doc.line(20, 170, 190, 170);
Tables organize data in a structured format, making information easier to read and understand.
// Simple table creation
const headers = [['Name', 'Age', 'City']];
const data = [
['John Doe', '30', 'New York'],
['Jane Smith', '25', 'Los Angeles'],
['Bob Johnson', '35', 'Chicago']
];
// AutoTable plugin (requires additional installation)
doc.autoTable({
head: headers,
body: data,
startY: 180,
theme: 'grid'
});
Colors enhance document appearance and help organize information visually.
// Set text color
doc.setTextColor(255, 0, 0); // Red text
doc.text('This text is red', 20, 200);
// Set fill color for shapes
doc.setFillColor(100, 150, 200);
doc.rect(20, 210, 40, 20, 'F');
// Set draw color for borders
doc.setDrawColor(0, 100, 0);
doc.setLineWidth(1);
doc.rect(70, 210, 40, 20);
Multi-page documents require proper page management and navigation.
// Add new page
doc.addPage();
// Set page dimensions for new page
doc.addPage('a4', 'landscape');
// Get current page number
const pageNumber = doc.internal.getCurrentPageInfo().pageNumber;
// Add page numbers
const totalPages = doc.internal.getNumberOfPages();
for (let i = 1; i <= totalPages; i++) {
doc.setPage(i);
doc.text(`Page ${i} of ${totalPages}`, 190, 280, { align: 'right' });
}
Headers and footers provide consistent document branding and navigation information.
// Add header to all pages
const totalPages = doc.internal.getNumberOfPages();
for (let i = 1; i <= totalPages; i++) {
doc.setPage(i);
// Header
doc.setFontSize(10);
doc.setTextColor(100);
doc.text('Company Name', 20, 10);
doc.text('Confidential Document', 190, 10, { align: 'right' });
// Footer
doc.text(`Page ${i} of ${totalPages}`, 105, 285, { align: 'center' });
}
Web forms can be converted to PDF documents, capturing user input for records or sharing.
// Function to generate PDF from form
function generatePDFFromForm() {
const formData = {
name: document.getElementById('name').value,
email: document.getElementById('email').value,
message: document.getElementById('message').value
};
const doc = new jsPDF();
// Add form data to PDF
doc.setFontSize(20);
doc.text('Form Submission', 105, 20, { align: 'center' });
doc.setFontSize(12);
doc.text(`Name: ${formData.name}`, 20, 40);
doc.text(`Email: ${formData.email}`, 20, 50);
doc.text(`Message: ${formData.message}`, 20, 60);
// Save the PDF
doc.save('form-submission.pdf');
}
Create interactive experiences where users can customize PDF content before generation.
// Interactive PDF generator
function createCustomPDF() {
const doc = new jsPDF();
// Get user preferences
const fontSize = document.getElementById('fontSize').value;
const textColor = document.getElementById('textColor').value;
const includeImage = document.getElementById('includeImage').checked;
// Apply user preferences
doc.setFontSize(fontSize);
doc.setTextColor(textColor);
// Add content based on preferences
doc.text('Custom PDF Document', 105, 20, { align: 'center' });
if (includeImage) {
doc.addImage('logo.png', 'PNG', 85, 30, 40, 40);
}
doc.save('custom-document.pdf');
}
Provide users with a preview of the PDF before final generation.
// Generate PDF preview
function generatePreview() {
const doc = new jsPDF();
// Add content
doc.text('Preview Document', 20, 20);
doc.text('This is a preview of your PDF', 20, 30);
// Convert to data URL for preview
const pdfData = doc.output('datauristring');
// Display in iframe
document.getElementById('preview').src = pdfData;
}
The most common use case is allowing users to download generated PDFs.
// Save PDF with custom filename
doc.save('my-document.pdf');
// Save with timestamp
const timestamp = new Date().toISOString().slice(0, 10);
doc.save(`document-${timestamp}.pdf`);
PDFs can be displayed directly in the browser without downloading.
// Open PDF in new tab
window.open(doc.output('bloburl'), '_blank');
// Display in iframe
const pdfData = doc.output('datauristring');
document.getElementById('pdfFrame').src = pdfData;
While jsPDF is client-side, you can integrate with server-side systems for storage or further processing.
// Send PDF to server
function uploadPDFToServer() {
const pdfBlob = doc.output('blob');
const formData = new FormData();
formData.append('pdf', pdfBlob, 'document.pdf');
fetch('/api/upload-pdf', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => console.log('PDF uploaded:', data))
.catch(error => console.error('Upload failed:', error));
}
Large PDF files can impact user experience and server storage costs.
Image Compression: Compress images before adding them to PDFs to reduce file size.
Font Optimization: Use standard fonts when possible to avoid embedding large font files.
Content Optimization: Remove unnecessary content and optimize text formatting.
// Optimize image before adding
function optimizeImage(imageData, maxWidth = 300) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = function() {
const ratio = maxWidth / img.width;
canvas.width = maxWidth;
canvas.height = img.height * ratio;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
const optimizedData = canvas.toDataURL('image/jpeg', 0.8);
doc.addImage(optimizedData, 'JPEG', 20, 20, maxWidth, canvas.height);
};
img.src = imageData;
}
Large documents can consume significant browser memory.
Page Limits: Consider breaking very large documents into multiple files.
Cleanup: Remove unnecessary objects and variables after PDF generation.
Streaming: For very large documents, consider server-side generation instead.
Robust error handling ensures smooth user experience.
function generatePDFWithErrorHandling() {
try {
const doc = new jsPDF();
// Add content with validation
if (!validateContent()) {
throw new Error('Invalid content for PDF generation');
}
doc.text('Document Content', 20, 20);
doc.save('document.pdf');
} catch (error) {
console.error('PDF generation failed:', error);
alert('Failed to generate PDF. Please try again.');
}
}
Plan your document structure before implementation to ensure professional results.
Content Hierarchy: Use consistent font sizes and styles for headings, subheadings, and body text.
Spacing and Margins: Maintain consistent spacing throughout the document for readability.
Brand Consistency: Use consistent colors, fonts, and styling that match your brand.
Ensure your PDFs are accessible to all users.
Text Structure: Use proper heading hierarchy and semantic structure.
Color Contrast: Ensure sufficient contrast between text and background colors.
Alternative Text: Provide descriptions for images and graphics when possible.
Thorough testing ensures professional-quality PDFs.
Cross-Browser Testing: Test PDF generation across different browsers.
Content Validation: Verify that all content appears correctly in generated PDFs.
Performance Testing: Test with large documents and various content types.
Issue: Text or images appear in wrong positions.
Solutions:
Issue: Text doesn't display correctly or uses wrong fonts.
Solutions:
Issue: Images appear blurry or distorted.
Solutions:
Issue: Generated PDFs are too large.
Solutions:
PDF generation with jsPDF opens up numerous possibilities for creating dynamic, professional documents directly in the browser. This client-side approach provides flexibility, reduces server load, and enables real-time document creation based on user input.
Key takeaways:
As you continue developing web applications, consider how PDF generation can enhance user experience by providing professional document creation and download capabilities. The skills learned in this lesson will help you implement robust PDF solutions in various contexts, from simple reports to complex, multi-page documents.