Invoice Generation Best Practices
Learn the best practices for generating professional invoices as PDFs, including layout tips, legal requirements, and optimization techniques.
Invoice Generation Best Practices
Generating invoices programmatically is a common requirement, but creating professional, compliant, and reliable invoice PDFs requires careful attention to detail.
Essential Components
Every professional invoice should include:
1. Company Information
<div class="company-info">
<img src="/logo.png" alt="Company Logo" />
<h1>Your Company Name</h1>
<p>123 Business Street<br />
City, State 12345<br />
TAX ID: XX-XXXXXXX</p>
</div>2. Invoice Details
- Invoice number (unique identifier)
- Issue date
- Due date
- Payment terms
- Purchase order number (if applicable)
3. Client Information
- Client name
- Billing address
- Contact information
- Client tax ID (if B2B)
4. Line Items
Use a well-structured table for clarity:
<table class="invoice-items">
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<!-- Line items here -->
</tbody>
<tfoot>
<tr>
<td colspan="3">Subtotal</td>
<td>$1,000.00</td>
</tr>
<tr>
<td colspan="3">Tax (10%)</td>
<td>$100.00</td>
</tr>
<tr class="total">
<td colspan="3">Total Due</td>
<td>$1,100.00</td>
</tr>
</tfoot>
</table>Layout Best Practices
Use a Grid System
Modern CSS Grid makes invoice layouts clean and responsive:
.invoice {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
.invoice-header {
grid-column: 1 / -1;
}Handle Page Breaks Properly
Never split important elements like line items or totals across pages!
Use CSS to control page breaks:
/* Prevent tables from breaking */
.invoice-items {
page-break-inside: avoid;
}
/* Keep totals together */
.invoice-totals {
page-break-inside: avoid;
}
/* Force new page for terms */
.invoice-terms {
page-break-before: always;
}Typography
Use clear, professional fonts:
body {
font-family: 'Inter', -apple-system, sans-serif;
font-size: 10pt;
line-height: 1.5;
}
h1 {
font-size: 24pt;
font-weight: 700;
}
.invoice-number {
font-size: 14pt;
font-weight: 600;
color: #2563eb;
}Legal Requirements
United States
- Invoice number
- Date of issue
- Seller information (name, address, tax ID)
- Buyer information
- Description of goods/services
- Amount due
- Payment terms
European Union
- VAT number (if applicable)
- VAT amount breakdown
- Reverse charge notice (if applicable)
- IBAN for payments
International
- Currency clearly stated
- Exchange rates (if applicable)
- Export documentation (for cross-border)
Always consult with a legal professional for your specific jurisdiction's requirements.
Optimization Tips
1. Use Web-Safe Fonts
Embed fonts to ensure consistency:
@font-face {
font-family: 'Inter';
src: url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700');
}2. Optimize Images
- Keep logos under 100KB
- Use SVG for vector graphics
- Compress PNGs/JPGs
- Consider embedding small images as base64
3. Minimize CSS
/* Bad: Multiple classes */
.blue { color: blue; }
.bold { font-weight: bold; }
.large { font-size: 16pt; }
/* Good: Semantic classes */
.invoice-total {
color: blue;
font-weight: bold;
font-size: 16pt;
}4. Template Variables
Use a templating system for dynamic data:
const invoiceTemplate = `
<div class="invoice">
<h1>Invoice #{{invoiceNumber}}</h1>
<p>Date: {{date}}</p>
<!-- ... -->
</div>
`;
const html = invoiceTemplate
.replace('{{invoiceNumber}}', invoice.number)
.replace('{{date}}', invoice.date);Using SyntaxDoc for Invoice Generation
With SyntaxDoc, you can generate professional invoices with a simple API call:
const response = await fetch('https://api.syntaxdoc.com/pdf/convert', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
html: invoiceHTML,
options: {
format: 'A4',
margin: { top: '20mm', right: '15mm', bottom: '20mm', left: '15mm' },
headerTemplate: '<div style="font-size: 8pt; text-align: center;">Invoice #{{invoiceNumber}}</div>',
footerTemplate: '<div style="font-size: 8pt; text-align: center;">Page <span class="pageNumber"></span> of <span class="totalPages"></span></div>'
}
})
});Advanced Features
QR Codes for Payments:
<div data-qr="PAYMENT:INVOICE:{{invoiceNumber}}:{{amount}}"></div>Watermarks for Unpaid Invoices:
{
"watermark": {
"text": "UNPAID",
"opacity": 0.3,
"fontSize": "72pt"
}
}Common Pitfalls
❌ Don't
- Use inline styles excessively
- Forget to test with multiple currencies
- Ignore page break handling
- Use overly complex layouts
- Forget accessibility considerations
✅ Do
- Use semantic HTML
- Test with various invoice lengths
- Implement proper error handling
- Version your invoice templates
- Keep archives of generated invoices
Sample Invoice Template
Next Steps
- Explore our invoice examples
- Learn about page break handling
- Add QR codes to invoices
- Implement watermarks
Ready to generate professional invoices? Get started with SyntaxDoc
Puppeteer vs wkhtmltopdf: A Complete Comparison
An in-depth comparison of Puppeteer and wkhtmltopdf for HTML to PDF conversion, including performance, features, and real-world use cases.
Handling Page Breaks in PDF Generation
Master the art of page breaks in HTML to PDF conversion. Learn how to control where content splits and keep important elements together.