PDFTron is now Apryse. Same great products, new name.

How to Generate a PDF with JavaScript

By Oscar Zhang | 2021 Mar 14

Sanity Image
Read time

8 min

A common requirement for web applications is a way to generate PDFs and make them available for download. This is typically to produce invoices, tickets, sales contracts, reports, and other documents personalized with customer data.

In this article, we walk you through a simple, open-source method: html2pdf.js. html2pdf uses a JavaScript library embedded in a website to make parts of it downloadable as PDFs. For this guide, we show how to generate a PDF from JavaScript in a web application from an HTML template.

Here are the steps we will follow to generate PDFs from an HTML template:

  1. Install html2pdf.js.
  2. Grab and convert a selection of HTML using the code we provide.
  3. Optional: Include additional methods, arguments, and parameters to control how the final PDF file displays and how the HTML content is split.

And here's the schema code we'll implement:

{
  "@context": "https://schema.org",
  "@type": "HowTo",
  "name": "Generate PDFs from an HTML Template",
  "step": [
    {
      "@type": "HowToStep",
      "name": "Install html2pdf.js",
      "text": "Install the html2pdf.js library to your project in order to convert HTML to PDF."
    },
    {
      "@type": "HowToStep",
      "name": "Grab and convert HTML",
      "text": "Use the provided code to select and convert a piece of HTML into a PDF file."
    },
    {
      "@type": "HowToStep",
      "name": "Optional: Customize PDF display and HTML content",
      "text": "You can use additional methods, arguments, and parameters to control how the final PDF file looks and how the HTML content is split."
    }
  ]
}

We also explore html2pdf.js use cases and alternatives – including an open-source React-to-PDF generator and Apryse’s advanced JavaScript framework for dynamic, serverless generation of interactive, paginated PDF documents.

html2pdf.js Use Cases

The html2pdf.js library relies on pure JavaScript to generate a PDF. As a result, html2pdf embeds directly client-side, in the browser. And unlike using the browser print function, html2pdf enables you to create an authentic download experience for your users. It works behind your interface and seems like a natural part of your web app.

html2pdf.js is good for small document generation. It’s perfect when you’re serving a single user who simply wants to click to create a PDF such as a concert ticket or a boarding pass.

html2pdf.js works well for certain functions:

  • Create and view simple PDFs with static, non-selectable content
  • Generate documents from an HTML/CSS template
  • Add a download-to-PDF function to a web app

How to Create a PDF from HTML with html2pdf.js

Combining html2canvas and jsPDF, html2pdf relies on a simple workaround to bypass typical challenges associated with converting HTML to PDF in a browser. First, it uses html2canvas to convert your HTML to a canvas and renders that canvas to a static image. It is then easy for jsPDF to wrap the new image in a PDF file, made downloadable to your users.

Getting Started

We’ve provided a manually typed HTML invoice template to use with this guide, but you can easily generate HTML for your own document in a backend.

Installation

html2pdf.js installs in three main ways: via HTML, by NPM, or by inserting the library using JavaScript.

HTML

The simplest way to install html2pdf.js is to download dist/html2pdf.bundle.min.js to your project folder and include it in your HTML with the following:

<script  src="html2pdf.bundle.min.js"></script>

NPM

You can also install html2pdf.js and its dependencies using NPM:

npm install --save html2pdf.js

JavaScript (Console)

Alternatively, if you’re on a web page you can’t modify directly and wish to use html2pdf.js for screenshot capture, paste the following into the console:

function addScript(url) {
  const script = document.createElement('script');
  script.type = 'application/javascript';
  script.src = url;
  document.head.appendChild(script);
}
addScript('https://raw.githack.com/eKoopmans/html2pdf/master/dist/html2pdf.bundle.js');

Basic Usage

Once html2pdf.js is installed, you can use it. The following code grabs and converts a selection of HTML, and then prompts the user to “save”.

const element = document.querySelector('body');
html2pdf(element);

Our example invoice then displays as such when opened:

Invoice template example view

Advanced Usage

If called without arguments, html2pdf.js returns a worker object. This worker in turn supports several methods and arguments. The library’s Promise-based API lets you chain methods sequentially, insert your own intermediate steps, or skip steps without difficulty.

For this guide, we won’t do anything fancy, instead sticking to the default flow:

// This will implicitly create the canvas and PDF objects before saving.
const worker = html2pdf().from(element).save();
// The basic workflow of html2pdf.js tasks (enforced by the prereq system) is:
// .from() -> .toContainer() -> .toCanvas() -> .toImg() -> .toPdf() -> .save()

Optional Parameter

In addition, html2pdf.js accepts an optional parameter with settings to control how the final PDF file displays and the to-image workaround used for conversion.

const element = document.querySelector('body');
const opt = {
  filename: 'myPage.pdf',
  margin: 2,
  image: {type: 'jpeg', quality: 0.9},
  jsPDF: {format: 'letter', orientation: 'portrait'}
};
// New Promise-based usage:
html2pdf().set(opt).from(element).save();
// Old monolithic-style usage:
html2pdf(element, opt);

Page-Break Examples

Lastly, we can programmatically add page breaks to our PDFs to control how the HTML content is split. Page breaks can be added via CSS styles, selectors on individual elements, or avoided (via the avoid-all mode).

// Avoid page-breaks on all elements, and add one before #pageX.
html2pdf().set({
  pagebreak: {mode: 'avoid-all', before:'#pageX'}
});
// Adds page-breaks according to the CSS break-before, break-after, and break-inside properties.
// Only recognizes always/left/right for before/after, and avoid for inside.
html2pdf().set({
  pagebreak: {mode: 'css' }
});

Short invoices don’t require page breaks. But you are required to add breaks on longer documents or documents with complex content, such as those with large images and tables, due to browser limits on how big canvases can get. (html2pdf uses a single canvas when creating each page.)

html2pdf.js Advantages

html2pdf.js is great if you want to create an authentic download experience for your users who want to produce simple PDFs from a webpage.

Since html2pdf.js merges information client-side, files do not cross a network multiple times. Therefore, it is reliable and infinitely scalable for each user that wants to download from your app. And your user experience is less impacted by any network latency or servers under heavy load.

Client-side implementation of html2pdf.js simplifies due diligence as well if your data is of a sensitive nature (e.g., personal, financial and/or health).

Infographic diagram of pdf document generation information flows

Serverless PDF generation improves the security, performance, reliability, and scalability of your download experience.

html2pdf.js Disadvantages

However, the library also has a few limitations noted by the open-source community. Many are tied to relying on the browser <canvas> workaround to produce a static image of content then wrapped in a PDF.

html2pdf.js limitations

  • Your PDFs won’t be interactive (i.e., no searchable and selectable text)
  • Rendering with html2pdf.js “isn’t perfect” since it relies on the built-in browser rendering function
  • You have to add pagination programmatically

You may also experience:

  • Larger file sizes due to producing pages as large images
  • Blurriness in text

HTML vs. Office Template Generation

Another consideration is using HTML vs. using templates in other formats such as Office (docx, pptx, and xlsx, as well as legacy Office formats).

HTML is great for simple documents where content is relatively static and/or limited to one page.

But it is less ideal for paginated documents, especially if your content needs to adjust dynamically when populated and it reflows across pages, since HTML was designed for webpages without pagination.

In contrast, Office templates have pagination baked into the logic of the format, making implementation of dynamic generation easier. As a bonus, users can upload their own templates in open Office formats created in their familiar Office tools. This makes it easy to recycle from an existing repository.

WebViewer has a built-in Office engine to generate PDFs from templates in Office formats, no servers, MS Office software, or MS Office licenses required. It drops into any web app directly and supports all modern frameworks including React, Angular, Vue, Blazor, etc.

html2pdf.js Alternatives

If you’d like to produce compact, high-fidelity PDFs with interactive (searchable/selectable) text, we’d suggest another method.

You can look at a number of open source libraries and methods. For example:

React-to-PDF Generation

One alternative we’ve written a tutorial on lets you create styled PDFs via a React PDF generator.

This React-to-PDF method works via a Node service and headless Chrome, and uses HTML templates. (Puppeteer and Babel-node are its dependencies.)

You are required to integrate a server component in order to handle the conversion. And if you’re fine with that, then you’re good to go.

Text and other content is not rendered via canvas as static images. As a result, React to PDF has advantages over html2pdf:

  • Your files are more compact
  • Your text is searchable and selectable
  • Your PDFs print faster and at higher fidelity
  • Complex content renders at higher fidelity

Severless, Dynamic Generation of Paginated PDFs

On the other hand, maybe you want the best of two worlds – an authentic download experience that you can embed in your app directly to generate beautiful, paginated PDF documents.

Next, we consider a solution that lets you:

  • Generate interactive, paginated and/or complex documents in the browser for your users to download or print
  • Leverage the same serverless advantages of html2pdf.js
  • Support additional features not easily possible with Puppeteer, such as form filling
  • Simplify tables that span pages

For this use case, consider our advanced JS framework – WebViewer from-Office template generation. This brings native, dynamic PDF generation into the browser to embed in any web app. As a result, it becomes very easy to create complex PDF documents in seconds.

WebViewer document generation is the same process for both client-side or server-side generation; it uses the same templates, the same APIs, and the same logic to create pixel-perfect documents. It merges in JSON data client-side and leverages any Office file templates (docx, pptx, xlsx, and legacy Office formats).

No servers, MS Office licenses, MS Office software, or plugins are required.

WebViewer JS Doc Gen Features

WebViewer uses pagination logic, so formatting is better. In addition, it has table spanning logic that creates headers consistently across all pages, whereas HTML breaks the header so it appears only on the first page.

Other WebViewer doc gen features include:

  • Automatic detection of your template styles and formatting
  • Dynamic reflow of text around added images and figures
  • Conditionals and loops

Finally, this technology leverages the leading accuracy of the Apryse SDK. So you can count on your PDFs to render and for content to reflow as expected. You also have access to the leading support and hundreds of other JS features of the Apryse SDK should you wish to extend your solution with additional document functionality such as form creation, watermarking, and so on.

How to Get Started with WebViewer JS PDF Generation

Apryse’s advanced JavaScript PDF generator requires minimal code to get up and running. Download WebViewer to your project and follow the instructions found in the from-Office generation guide. Later, you can consider extending your solution. Dive deep into the PDF generation library or WebViewer’s many other serverless capabilities.

Wrap Up

Generating a PDF from a website using JS is no piece of cake. But following this guide, you can now generate a PDF with JavaScript, like invoices, right in your web app and make those PDFs downloadable by your users!

We also looked at html2pdf.js use cases and alternatives such as a React PDF generator.

The bottom line: If you need a quick, simple conversion and don’t care about pagination, html2pdf is a good serverless PDF gen component. However, if you need to create more complex documents or if formatting is important, check out WebViewer’s document generation framework. It also lets you embed a fast, authentic download experience for your users, and it provides more flexibility than alternatives via its serverless PDF generator.

Sanity Image

Oscar Zhang

Share this post

email
linkedIn
twitter