SyntaxdocSyntaxdoc
Blog

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;
}

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

Ready to generate professional invoices? Get started with SyntaxDoc

On this page