jsPDF Invoice Generator with Live PDF Preview — Free JavaScript Snippet

jsPDF Invoice Generator with Live PDF Preview · Tools · Plain HTML, CSS & JS · Live preview

What's included

Features

Client-side PDF generation
No server, API key or headless browser.
Real text PDF
Selectable, searchable and small.
autoTable line items
Wrapping, widths and page breaks handled.
Computed totals
Subtotal, tax and total due.
Live PDF.js preview
The actual generated file, rendered to canvas.
Stale render protection
A token drops outdated previews.
Detached-buffer safe
Copies bytes before handing them to PDF.js.
Currency and date formatting
Locale-aware numbers and dates.

About this UI Snippet

jsPDF Invoice Generator — A Real PDF, Built and Previewed in the Browser

Screenshot of the jsPDF Invoice Generator with Live PDF Preview snippet rendered live

Generating an invoice PDF usually means a server, a headless browser or a paid API. For many apps that's unnecessary: jsPDF can draw a complete, text-based PDF in the browser, and PDF.js can render it back so users see exactly what they'll download. This snippet combines both into a small invoicing tool.

Drawing with jsPDF

The document is built in millimetres on A4. The header is a filled rectangle with white text; addresses are wrapped to a column width with splitTextToSize, which returns an array of lines jsPDF can print directly; right-aligned figures use { align: 'right' } with the x coordinate at the right margin. Text stays real text in the PDF, so it's selectable and searchable.

Tables with jspdf-autotable

Hand-positioning table rows gets painful as soon as a description wraps. The autotable plugin handles column widths, wrapping, row heights and page breaks. After it runs, doc.lastAutoTable.finalY tells you where the table ended, which is where the totals are drawn.

Previewing the real output

The preview isn't an HTML imitation. Every edit regenerates the PDF, and PDF.js renders page one onto a canvas at the device pixel ratio. A render token discards results from older edits so fast typing never shows a stale page.

A gotcha worth knowing

PDF.js *transfers* the ArrayBuffer you give it to its worker, which detaches it. If you still need the bytes — to upload them, or load them into another library — pass a copy with bytes.slice(0), otherwise the next use fails with "Cannot perform Construct on a detached ArrayBuffer".

Downloads and sandboxes

doc.save() triggers a download. Sandboxed iframes (such as this site's live preview) block downloads unless they allow them, so the status message tells users to open the demo in its own tab. In a normal page it works directly.

Fonts

The built-in Helvetica covers $, £ and €. For other currency symbols or scripts, embed a TTF font with addFileToVFS and addFont.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet into an AI assistant like Claude and ask it to explain how autoTable's finalY lets the totals follow a table of any length. Ask it to add a logo image, a second page of terms, embedded fonts for other currencies, invoice numbering saved per client, or emailing the PDF bytes to an API endpoint. It can also review rounding: whether tax should be calculated per line or on the subtotal for your country.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a browser-based invoice generator with jsPDF and the jspdf-autotable plugin, previewing the generated file with PDF.js 3 (all loaded from a CDN), in plain HTML, CSS and JavaScript.

Requirements:
- A form with invoice number, date, "from" and "bill to" addresses, editable line items (description, quantity, rate, remove) with an add-line button, a currency select ($, £, €) and a tax percentage.
- Build an A4 PDF in millimetres: a coloured header with "INVOICE", number and formatted date; wrapped address blocks; a line-item table with autoTable (right-aligned numeric columns); subtotal, tax and bold total drawn after the table's final y position; a footer note.
- Regenerate the PDF on every edit (debounced), render page one with PDF.js onto a canvas at the device pixel ratio, ignore outdated renders, and show the file size. Pass PDF.js a copy of the bytes.
- A Download button that saves the PDF using the invoice number as the file name and notes that sandboxed previews may block downloads.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="jiv">
  <form class="jiv-form" id="jivForm" autocomplete="off">
    <h2>Invoice</h2>
    <div class="jiv-row">
      <label>Invoice no. <input name="no" value="INV-2026-0142"></label>
      <label>Date <input name="date" type="date" value="2026-09-25"></label>
    </div>
    <div class="jiv-row">
      <label>From <textarea name="from" rows="3">Northwind Studio
12 Harbour Street
Bristol BS1 4ZZ</textarea></label>
      <label>Bill to <textarea name="to" rows="3">Parcelly Ltd
Attn: Accounts
Leeds LS1 2AB</textarea></label>
    </div>
    <div class="jiv-items">
      <div class="jiv-ihead"><span>Description</span><span>Qty</span><span>Rate</span><span></span></div>
      <div id="jivItems"></div>
      <button type="button" id="jivAdd" class="jiv-link">+ Add line</button>
    </div>
    <div class="jiv-row">
      <label>Currency <select name="cur"><option value="$">USD $</option><option value="£">GBP £</option><option value="€">EUR €</option></select></label>
      <label>Tax % <input name="tax" type="number" min="0" max="50" step="0.5" value="20"></label>
    </div>
    <div class="jiv-actions">
      <button type="button" id="jivDownload">Download PDF</button>
      <span id="jivStatus" role="status"></span>
    </div>
  </form>
  <div class="jiv-preview">
    <div class="jiv-plabel">Live preview of the generated PDF <small id="jivSize"></small></div>
    <canvas id="jivCanvas" aria-label="Rendered invoice PDF"></canvas>
  </div>
</div>

Step by step

How to Use

  1. 1
    Load the librariesjsPDF, jspdf-autotable and PDF.js from the CDN.
  2. 2
    Edit the invoiceChange addresses, line items, currency and tax; the preview updates.
  3. 3
    Add or remove linesThe table grows and totals recalculate.
  4. 4
    DownloadSaves a real PDF named after the invoice number.
  5. 5
    Style itChange colours and layout in build(); the preview shows the result.

Real-world uses

Common Use Cases

Freelancer tools
Generate invoices without a backend.
SaaS billing pages
Downloadable receipts in the dashboard.
E-commerce
Order confirmations and packing slips.
Internal tools
Quotes, purchase orders and reports.
Offline apps
PDF export that works without a network.
Related: jsPDF Certificate Generator
Landscape layouts and custom fonts: jsPDF Certificate Generator.
Related: PDF.js Viewer with Thumbnails
A full viewer for any PDF: PDF.js Viewer with Thumbnails and Zoom.

Got questions?

Frequently Asked Questions

Create a document with new jspdf.jsPDF({ unit: 'mm', format: 'a4' }), draw text, lines and shapes with coordinates in those units, then call doc.save('file.pdf') to download or doc.output('arraybuffer') to get the bytes.

Load the jspdf-autotable plugin and call doc.autoTable({ head, body, startY }). It handles column widths, text wrapping and page breaks, and doc.lastAutoTable.finalY gives the y position where the table ended.

Get the bytes with doc.output('arraybuffer'), load them with PDF.js (pdfjsLib.getDocument), and render a page to a canvas. This shows the real file rather than an HTML approximation.

PDF.js transfers the buffer you pass to its worker, which detaches it in your code. Pass a copy (bytes.slice(0)) to PDF.js if you need to use the original bytes again.

Sandboxed iframes block downloads unless they include allow-downloads. Open the demo in its own tab, or in your own site the download works normally.